Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

Day 9 of 30 · about 28 minutes

Functions that tidy your code: a Morse sender

Today you build: A Morse code sender you type into

  • Read 5 min
  • Upload & send SOS 5 min
  • Try it 18 min

Community draft — report a mistake

By now your sketches have the same few lines copied around. A function gives those lines a name, so you write them once and call them anywhere.

Wiring

Nothing new. The sketch uses the on-board L LED (pin 13) and, if it’s still on the breadboard, day 6’s passive buzzer on pin 8.

Three kinds of function

The sketch has one of each:

  • void beep(int units) — takes a parameter and does something. void means it gives nothing back.
  • const char* morseFor(char c) — takes a letter and returns its Morse pattern, like ".-" for A. If there isn’t one, it returns nullptr (“nothing”), and the caller checks for that.
  • void sendLetter(char c) — builds on the other two. Small functions that call other small functions are much easier to read than one long loop().

Morse timing

Everything is a multiple of one unit (UNIT_MS, 120 ms): a dot is 1 unit, a dash 3, the gap inside a letter 1, between letters 3, between words 7. Change UNIT_MS and the whole message speeds up or slows down — that’s the payoff of naming a number once.

Use it

Upload, open the Serial Monitor at 9600 baud, type SOS and press Enter. Each letter prints with its pattern while it plays.

Good function habits

  1. One job per function. If the name needs “and”, split it.
  2. Names that say what it does: readCm(), showLevel(), not doStuff().
  3. Pass values in as parameters instead of reading global variables, when you can — it makes the function reusable in the next sketch.

Try it

  • Add digits 0–9 (look up their patterns) with a second array.
  • Write void blinkTimes(int pin, int times) and use it to blink the count of letters sent.

You’re done when…

  • Typing SOS prints S ..., O ---, S ... and the LED (and buzzer) play short-short-short, long-long-long, short-short-short.
  • Lower-case sos plays the same; digits and punctuation are skipped without an error.
  • Halving UNIT_MS to 60 makes the whole message twice as fast.

Today's code

Verified — core avr 1.8.8, 3 Nov 2026Compile-only
lesson-morse.inoArduino C++Open in PlaygroundOpen in Playground
// Day 9 — Functions that tidy your code (Arduino Uno / Nano)
// Type a word in the Serial Monitor (9600 baud) and the board sends it in Morse code
// on the "L" LED (pin 13) and, if you kept day 6's wiring, on the passive buzzer (pin 8).

const int LED_PIN = 13;
const int BUZZER_PIN = 8;
const int UNIT_MS = 120;   // one "dot"; everything else is a multiple of this

// Morse for A..Z. MORSE[0] is A, MORSE[1] is B, and so on.
const char* const MORSE[26] = {
  ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
  "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};

// Turn LED and tone on for a number of units, then off.
void beep(int units) {
  digitalWrite(LED_PIN, HIGH);
  tone(BUZZER_PIN, 700);
  delay(units * UNIT_MS);
  digitalWrite(LED_PIN, LOW);
  noTone(BUZZER_PIN);
}

// Returns the Morse pattern for a letter, or nullptr if there isn't one.
const char* morseFor(char c) {
  if (c >= 'a' && c <= 'z') c = c - 'a' + 'A';   // accept lower case too
  if (c < 'A' || c > 'Z') return nullptr;
  return MORSE[c - 'A'];
}

void sendLetter(char c) {
  if (c == ' ') {               // gap between words: 7 units (3 already waited + 4)
    delay(4 * UNIT_MS);
    return;
  }
  const char* code = morseFor(c);
  if (code == nullptr) return;  // skip digits and punctuation
  Serial.print(c);
  Serial.print(F("  "));
  Serial.println(code);
  for (int i = 0; code[i] != '\0'; i++) {
    beep(code[i] == '.' ? 1 : 3);   // dot = 1 unit, dash = 3 units
    delay(UNIT_MS);                 // 1 unit between dots and dashes
  }
  delay(2 * UNIT_MS);               // 3 units between letters (1 already waited)
}

void setup() {
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);
  Serial.println(F("Type a word and press Enter, e.g. SOS"));
}

void loop() {
  if (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '\n' || c == '\r') return;
    sendLetter(c);
  }
}

↑↓ to move · Enter to open