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.voidmeans 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 returnsnullptr(“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 longloop().
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
- One job per function. If the name needs “and”, split it.
- Names that say what it does:
readCm(),showLevel(), notdoStuff(). - 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
SOSprintsS ...,O ---,S ...and the LED (and buzzer) play short-short-short, long-long-long, short-short-short. - Lower-case
sosplays the same; digits and punctuation are skipped without an error. - Halving
UNIT_MSto60makes the whole message twice as fast.
Today's code
// 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);
}
}// 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);
}
}