Week 4: Embedded Programming¶
Research¶
Years ago, before I’d even know how to write code, I came across the binary tree representation of the Morse Code. It looked a bit complicated, but once I knew how to traverse through tree nodes, the tree representation was more than logical.
The Morse Code is comprised of dots and dashes, whereas the parent nodes are prioritezed to have the most frequently occuring letters. Naturally we start with E and T. To get a letter/charactere we treverse down the tree as follows: dots to the left, dashes to the right.

To get my name I would go down all the way to the right, to the 4th level:
H → •••• // left > left > left > left
R → •-• // left > right > left
A → •– // left > right
C → -•-• // right > left > right > left
H → •••• // left > left > left > left
Week’s Project¶
After much thinking, an interesting, yet useful project with simple I/O devices was a Morse Code decoder.
The make a Morse Code decoder you need:
1x Arduino UNO
1x LCD
1x LED
2x 220Ω resistors
1x 10kΩ resistor
1x 100kΩ potentioemeter
1x 0.03Ω button
?x male-to-male jumper wires

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
const int ledPin = 8;
const int buttonPin = 9;
int inputCol = 7; // Start after "Input: "
int outputCol = 8; // Start after "Output: "
String outputText = ""; // Store all decoded letters
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
unsigned long dotDuration = 0;
unsigned long dashDuration;
unsigned long nextCharDuration;
unsigned long spaceDuration;
unsigned long startTime;
unsigned long pressTime;
unsigned long releaseTime;
String currentMorse = "";
// Morse table
struct MorseMap {
const char* code;
char letter;
};
MorseMap morseTable[] = {
{".-", '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'}
};
char decodeMorse(String code) {
for (int i = 0; i < 26; i++) {
if (code == morseTable[i].code) {
return morseTable[i].letter;
}
}
return '?';
}
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
lcd.begin(16, 2);
lcd.print("Press 3 dots.");
unsigned long totalDuration = 0;
// --- Calibration ---
for (int i = 0; i < 3; i++) {
while (digitalRead(buttonPin) == LOW);
digitalWrite(ledPin, HIGH);
startTime = millis();
while (digitalRead(buttonPin) == HIGH);
digitalWrite(ledPin, LOW);
pressTime = millis() - startTime;
totalDuration += pressTime;
}
dotDuration = totalDuration / 3;
dashDuration = dotDuration * 3;
nextCharDuration = dotDuration * 3;
spaceDuration = dotDuration * 7;
lcd.clear();
lcd.print("Input:");
lcd.setCursor(0, 1);
lcd.print("Output:");
}
void loop() {
if (digitalRead(buttonPin) == HIGH) {
digitalWrite(ledPin, HIGH);
startTime = millis();
while (digitalRead(buttonPin) == HIGH);
digitalWrite(ledPin, LOW);
pressTime = millis() - startTime;
// Add dot or dash to Morse input
lcd.setCursor(inputCol, 0);
if (pressTime < dashDuration) {
lcd.print(".");
currentMorse += ".";
} else {
lcd.print("-");
currentMorse += "-";
}
inputCol++; // Move cursor forward
releaseTime = millis();
}
// Detect gaps
if (currentMorse.length() > 0) {
unsigned long gapTime = millis() - releaseTime;
// End of character
if (gapTime > nextCharDuration && gapTime < spaceDuration) {
char decoded = decodeMorse(currentMorse);
outputText += decoded;
lcd.setCursor(outputCol, 1);
lcd.print(decoded);
outputCol++; // Move cursor forward
currentMorse = "";
}
// Word space
if (gapTime >= spaceDuration) {
outputText += " ";
lcd.setCursor(outputCol, 1);
lcd.print(" ");
outputCol++;
currentMorse = "";
}
}
}
Output¶
Please watch the demo video