Morse Messenger – SCOPES-DF

Lesson Details

Age Ranges *
Fab Tools *
Standards
Fab-Electronics.1, 8.L.3, 7.L.3, 6.L.3, Fab-Programming.3
Author

Author

Joe Cantu
Joe Cantu
K-12 teacher
Joe C Cantu II is an American craftsman, designer, and musician based out of the Lydia Sneed Engineering Lab at Metairie Park Country Day School. A graduate of the Ball State University, He has most recently attended Fab15 in Egypt,… Read More

Summary

In the beginning, Samuel flipped a switch. And again, and again. 

44 miles away, his assistant heard an eerie sound, and soon understood the words, “What hath God Wrought?”

 

Well, 1844 may not have been THE beginning, and that first telegraphic message may have been a little dramatic, but the importance of the moment involved the translation of text from a format that was already the most widely distributed in the world, to a whole new method of near instantaneous communication. But what WAS it?

 

The library of Congress documents the record of this message as a paper copy with raised dots and dashes, made to be translated later by an operator. How was it made? In this lesson, a simple circuit will show the simplest way to achieve a morse code messenger. Then, a modern touch adds a microcontroller to help with rapid translation. 

 

https://www.morsewords.com/

https://www.loc.gov/item/mmorse000107

 

 

 

This lesson introduces students to concepts of abstraction through one of the oldest forms of electronic communication known, the Morse Code. Through an interactive primer, students gain experience with the precursor to binary logic, and practice a few basic circuitry skills as well. 

 

In addition to those documented, this lesson also aligns with the following standards:

CSTA K-12 (2-CS-02): Design projects that combine hardware and software components

ISTE Student Standard 5c (Computational Thinker): Break problems into component parts, extract key information to develop descriptive models

What You'll Need

This lesson builds a circuit with

  • an LED
  • A 220 Ohm resistor for the LED
  • A momentary pushbutton
  • a 10k resistor
  • a buzzer
  • A breadboard
  • An Arduino

This lesson also depends on the following vocabulary terms:

  • Abstraction: simplification of a concept to be able to be delivered through simpler means.
  • Function – a named group of programming instructions. Also referred to as a “procedure”.
  • Function Call – a command that executes the code within a function
  • Conditional – affects the sequential flow of control by executing different statements based on the value of a Boolean expression
  • Variable – a named reference to a value that can be used repeatedly throughout a program
  • int – integer type variable
  • char – character type variable

 

Learning Objectives

Students will build a circuit from physical parts or model one in TinkerCAD Circuits, which can be directly interacted with or programmed.

Students will investigate the abstraction at the heart of Morse code, and explain in their own words how it simplifies letters and numbers into pulses of light and sound.

Students will practice writing statements in Arduino C with variables, and conditionals.

Students will use their circuit and programmed model to communicate a message of their choosing, verifying that it does so effectively.

Students will communicate with a collaborative partner to encode and decode messages, and reflect on challenges with the model and medium.

Reflection

  1. The biggest challenge of the project becomes decoding. The activity wanders through a variety of Computer Science fundamental concepts, and even touches circuitry basics, with a project that is technically capable of demonstrating the core concept of abstraction. However, key to the abstraction is that information is able to flow both ways across the encoding … While students can gain some fluency in tapping out their name on the manually operated tap-circuit, and they can certainly enter words into the Serial Monitor and listen and watch the pulses the emanate from their device. But when I put them into pairs, the ones tasked with decoding found that information came at them too quickly to feel confident doing so. Multiple partner groups expressed varying degrees of frustration with the manual decoding process, and several seemed to give up all together, or take the opportunity to simplify their messages to ease the burden of decoding… This actually expresses a secondary form of abstraction and might have presented another opportunity to reinforce that topic. Nevertheless, the activity may need a decoding method compatible with the encoder.
  2. With upper school students, The pace assumed fairly confident typing skills, and blocking could go more or less in sequential order. I have done similar activities before with this group, and had already done some coverage on domain-vocabulary with this audience. I used the growing confidence to bolster progress so that students spent less time waiting for the next objective. Having also recognized a goal of doing an activity of doing this activity with younger or less experienced students, I broke the program up into smaller chunks, and spent a little more time talking through what these chunks do for the whole code.
  3. I tried breaking the code down into smaller chunks, and giving students more opportunities to stop and test their code as we went along, and specifically giving them instruction on self-testing instead of stopping to ask the instructor. Students would could self-test on objective achievement, even if not all of them do, seems to reduce barriers and allow for instructional aid to make it to students who need more support without impeding those who don’t.
  4. I would definitely add a method for having a mechanism for receiving and decoding the morse pulses, and even giving project partners the ability to communicate across some distance, so that they are able to feel more thorough about inspecting and understanding the abstraction process at hand. We do this already with binary, earlier in the semester, and a method for such here would help reinforce abstraction even for those who might have missed the concept the first time around. I also have started adding acknowledgements to vocabulary terms, and want to add pre-teaching aids for them.

 

The Instructions

Circuit Prototype:

Add the LED, button, and buzzer to the breadboard. The spacing shown is intended to facilitate fingers still practicing the kind of nimble positioning a breadboard can command, with components spaced relatively far apart, so connections can be made without interfering with existing ones.

Start with the breadboard, and use the LED to stand on opposite sides of what is called “the ravine.”

  • With the breadboard oriented vertically in front of you, set the long leg (also called the anode) into a row to the left of the long empty section in the middle of the board. The short leg (cathode) will reach across to a row on the other side. 
  • It can be the same row, since the rows themselves do not cross the ravine. Along the row where the short leg has reached, insert one of the legs of the 220 Ω resistor. The other leg of the resistor will go to the long blue or black “ground row” along the nearest side of the board. 

Add the button to the breadboard, also across the ravine, it appears to have 4 spots to which anything could be connected.

  • No worries, this doesn’t mean a whole lot of complication.
  • To the row at the upper right of the button, add the 10kΩ resistor, connecting it to the ground row. Connect a wire from the top left of the button to the anode of the LED. 
  • The lower left OR lower right terminals can connect to the positive terminal of the power supply. 

The power supply can be a battery, 2 AA’s in a holder is one format which could work.

  • Alternatively, the Arduino itself can supply power from the 5V pin, with the ground row connecting to the negative terminal if using the battery, or the GND pin of the Arduino. 

If desired, the buzzer (piezo transducer) can be added to the board on a different row, with its positive terminal also on the left. A wire can connect its negative terminal to the ground row. 

  • Connect its positive side to the row with the top left of the button with a wire. 

Included images show both configurations.

  • Between the button and LED, our circuit is series, meaning there is only one path for electricity to follow through components to ground.
  • When we add the buzzer, the new circuit is parallel.
  • This means that electricity can flow either through the buzzer or the light, and if either component should fail, there is still a path through the other. 

 

From here, each time the button is pushed, the light will illuminate and the speaker will buzz, if only faintly. 

  • Use the included Morse chart to practice using the button to display your name in the flashing of the light. 

 

What other ways can we use electricity to send messages with only 2 options?

  • This leads us to the computer, if over a course of nearly 100 years. 

 

Building the programmable messenger

The early pioneers of the computer developed a new systematic approach to expressing the complexity of challenges with computing. Binary was a lot like morse, in that there were only 2 options… so why not just use the same method?

While we think of morse as being based on 2 options, called the dit and the dash, it actually turns out there was a third option. SPACE. Telegraph operators would pause between each pulse, a gap that distinguished between any two pulses in a letter, a different one between letters in a word, a longer one between words, and longer still between statements. This variety was also often inconsistent between operators, who were invariably human. Computers are capable of remarkable consistency, and this segment will address the concept of abstraction. First as a part of making morse code out of letters numbers and punctuation that we understand, and converting them back again. Then, abstracting in a slightly different way to send any and all kinds of data in the ones and zeros of binary code. Binary gave rise to languages like BASIC, then FORTRAN, and COBAL and eventually JAVA and C, C++, and C#. This is by no means a hierarchical list of all languages, which all approach abstraction between the what needs to be encoded and the code that results. 

 

For this activity, it’s time to actually used the Arduino, and not just for power.

So, if the original circuit was built with a battery, its time to remove it.

Use wires to connect from the button input to the 5V port on the Arduino, and from the ground row to one of the GND ports on the Arduino.

Next, adjust the wires connecting the LED and buzzer to the button. Now they should connect to ports 13 and 4 on the Arduino. One more wire is needed to connect the button to port 2.

Then we program.

Programming the messenger

Open an Arduino sketch, or a TinkerCAD Circuits document.

The program opens with a set of variables, which serve to hold values to be used elsewhere in the program.

int dot = 76;
int dash = dot*3;
int pause = dash;
int wait = dot*7;
int speaker = 4;
int light = 13;
int button = 2;

Note how some of these don’t seem to have their own values, as much as they do some math to other values that already existed.

  • This is one of the most useful things about variables, along with being able to define a value in one place, making updates easier.
  • The word “int” labels each one as an integer, as that is what kind of value we are storing there.
  • Also remember that each line here is a “statement” of code and ends in a semicolon.

 

Next, one of Arduino’s two primitive functions, which must be included in order to run the program:

void setup() {
  •  Here, the word “void” is actually a placeholder. 
  • It means empty, and is holding a place for something called a return type.
  • If the function was intended to have any output values, they would be described here with a different word.
  • “setup” is of course the name of the function
  • The “()” after the name are a container which might be filled with any inputs a function might need.
  • In this case, there are none, so leave them empty and go on.
  • The “{” defines the opening of the function. Later, that will be followed by a closing.

 

This function is called setup, so it seems reasonable that it should be used to specify things like whether the connected pins are serving as inputs or outputs.

 pinMode(light, OUTPUT);
 pinMode(speaker, OUTPUT);
 pinMode(button, INPUT);

 Next, start the Serial Monitor so the code can be interacted with via text while it is running.

 Serial.begin(9600);
 while (!Serial) {
      ; // wait for serial port to connect. Needed for native USB port only
 }
 
 // send an intro:
 Serial.println("Send me text, and I will broadcast in Morse!");
 Serial.println();

 Note here that “println” is not a mashup of “print in” or even “print 1 n” but of “print line” with a couple of missing vowels.

 

Time to close the setup function. Do so with:

  }

 The other primitive function in Arduino may also be included already:

void loop() {
 
}

 Leave that one unchanged for now, it will be filled in after the next step. 

 

At this stage, test to verify that the code will let the user open the Serial Monitor and send through a few characters, and prove that they are received.

Making a new function.

Moving beyond the two basic functions, its now time to build a whole new function, to handle the most repetitive part of the program.

In the space AFTER the closing bracket of the loop() function, create a new function called “tap”

	void tap( int toneLength) {

How many outputs and inputs does this function have? How can that be known?

 

This function needs to both turn on the LED and play a tone on the buzzer. 

	digitalWrite(light, HIGH);
	tone(speaker, 3000, toneLength);

Here, the number in the middle of the tone statement sets the pitch of the note played. 

Modify it to make it unique. (in case of learners with sensory sensitivities, this is a good one to suggest to bolster their agency about it.)

	delay(toneLength);

Whether the tap is for a dit or a dash, the length will be passed to here, which will hold the light and sound for that amount of time. 

	 digitalWrite(light, LOW);
	 delay(dot);
	}

Once the tap is done, turn the light off (the tone function sets its own ending), and pause for the length of one dit, the standard spacing between elements in morse. That’s the end of the custom function. 

 

Test the code by adding function calls into the loop() function,

try things like:

tap(dot); 
tap(dash); 

 

Conditionals and Nesting

It's now time to fill in the loop() function.

The first line uses an if statement to check whether any characters have been received by the Serial Monitor.

  // get any incoming bytes:
 if (Serial.available() > 0) {
  char thisChar = toupper(Serial.read());
 
   // say what was sent:
   Serial.print("Broadcasting: ");
   Serial.println(thisChar);
 
}

 Note that the phrase “Serial.available() > 0” is inside parenthesis, like inputs and it is followed by a { , like a function. Inside a new type of variable, this one a “char,” which stores the character which is read from the serial monitor, converting it to uppercase. What happens if no characters are available?

 

With conditional statements, if the condition is not met, the statement inside it does not execute.

 else {
  // read the state of the pushbutton
  int buttonState = digitalRead(button);
   // check if pushbutton is pressed.
   // if it is, the button state is HIGH
   if (buttonState == HIGH) {
     digitalWrite(light, HIGH);
     tone(speaker, 3000, dot);
   } else {
     digitalWrite(light, LOW);
   }
   delay(10); // Delay a little bit to improve performance
 }

 This will execute if there is no input from the serial monitor, and would allow the user to push the button for a manual mode.

 

In order to complete the translator, a conditional statement is needed which has more than two options.

 

Add a new line after “Serial.println(thisChar);”

 

Begin the new statement like so:

 switch (thisChar) {
           case 'A': tap(dot); tap(dash); delay(pause); break;
           case 'B': tap(dash); tap(dash); tap(dash); tap(dot); delay(pause); break;
           case 'C': tap(dash); tap(dot); tap(dash); tap(dot); delay(pause); break;
           case 'D': tap(dash); tap(dot); tap(dot); delay(pause); break;
           case 'E': tap(dot); delay(pause); break;     
           default:  delay(wait); break;
           }

 In this statement, the letter stored in “thisChar” is compared against each case in the switch.

If a match is found, the statements after it execute until the “break;”

Of course, in order to find matches for letters after “E,” more “case” statements will be needed.

This is probably the easiest place for students with high confidence to race ahead on setting up all the case statements for the rest of the alphabet, or even numbers and symbols.

 

Once enough case statements have been added, upload the code and open the Serial monitor to input phrases to be translated, then watch and listen to the message as displayed in morse taps. 

 

Then, pair up with someone else who has a working prototype, and practice sending and receiving messages between each other. What challenges are encountered? Reflect and pose solutions.

After Some thought...

A revised sketch is included in the attachments with allows two boards to send and receive messages encoding and decoding alike.

the LED port of one board can be routed with a wire to the Button port of another.

At minimum, a wire should also span between the ground ports of the boards to ensure common ground.

With a third wire running the opposite path between LED and Button, each board is capable of sending morse that is either tapped out on the button, or typed into the Serial monitor, to be received on the other board and displayed in light, buzzer, and serial monitor as well.

This solved the problem of no support for receiver, and only requires teaching about millis() and the unsigned long data type. 

Standards

  • (Fab-Electronics.1): I can follow instructions to build a simple electrical circuit using conductive material, basic components, and power.
  • (8.L.3): Use knowledge of language and its conventions when writing, speaking, reading, or listening.
  • (7.L.3): Use knowledge of language and its conventions when writing, speaking, reading, or listening.
  • (6.L.3): Use knowledge of language and its conventions when writing, speaking, reading, or listening.
  • (Fab-Programming.3): I can create a program with multiple instructions and branching elements as well as reading / controlling inputs and outputs on a microcontroller board.

Lesson Feedback

Contact us

Having trouble? Let us know by completing the form below. We'll do our best to get your issues resolved quickly.

"*" indicates required fields

This field is for validation purposes and should be left unchanged.
Name*
Email*
?