Built-in project · ESP32-C3-DevKitM-1
Morse sender on an ESP32-C3
An ESP32-C3 sends a word in Morse on a lamp and a piezo at once, and a button picks the next message. The whole build, an ESP32-C3 and 4 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
BeginnerRuns in your browser. Free, and no account needed.
Hold the button
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
sketch.ino · ESP32-C3-DevKitM-1
// Morse: a word sent as light and sound, one element at a time.
//
// GPIO 8 the lamp, through 220 ohm to GND
// GPIO 5 a passive piezo straight to GND
// GPIO 9 a button to GND, internal pull-up: send the next message
//
// Morse is built out of one unit of time. A dot is one unit, a dash is three,
// the gap inside a letter is one, between letters three, between words seven.
// Everything below is that table and nothing else, so changing UNIT_MS changes
// the speed of the whole thing and every proportion stays right.
//
// Twenty words a minute is the usual yardstick, and the word it is measured on
// is PARIS, which is fifty units long: 60 000 / (20 x 50) is 60 ms a unit. The
// sketch starts slower than that, at 120 ms, because it is meant to be read
// off the lamp by eye.
//
// The table is one string a letter, dots and dashes, indexed by the letter
// itself. Anything not in it is skipped, so punctuation in a message costs
// nothing but is not sent either.
#include "mokxi_tone.h"
const uint8_t LAMP = 8;
const uint8_t PIEZO = 5;
const uint8_t BUTTON = 9;
const uint16_t UNIT_MS = 120;
const uint16_t PITCH_HZ = 700;
// A to Z, then 0 to 9.
const char *const MORSE[] = {
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..",
".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.",
"...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----",
".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.",
};
const char *const MESSAGES[] = {"SOS", "MOKXI", "HELLO WORLD"};
const int MESSAGE_COUNT = 3;
int which = 0;
static const char *codeFor(char c) {
if (c >= 'a' && c <= 'z') {
c = (char)(c - 'a' + 'A');
}
if (c >= 'A' && c <= 'Z') {
return MORSE[c - 'A'];
}
if (c >= '0' && c <= '9') {
return MORSE[26 + (c - '0')];
}
return 0;
}
// One element: the lamp and the note together, for one unit or three.
static void element(bool dash) {
uint16_t ms = (uint16_t)(dash ? UNIT_MS * 3u : UNIT_MS);
digitalWrite(LAMP, HIGH);
mokxiTone(PIEZO, PITCH_HZ, ms);
digitalWrite(LAMP, LOW);
delay(UNIT_MS); // the gap inside a letter
}
static void sendLetter(const char *code) {
for (const char *p = code; *p; p++) {
element(*p == '-');
}
delay(UNIT_MS * 2u); // one unit is already spent, three between letters
}
static void send(const char *text) {
Serial.print("sending ");
Serial.println(text);
for (const char *p = text; *p; p++) {
if (*p == ' ') {
delay(UNIT_MS * 4u); // three are already spent, seven between words
continue;
}
const char *code = codeFor(*p);
if (!code) {
continue;
}
Serial.print(" ");
Serial.print(*p);
Serial.print(" ");
Serial.println(code);
sendLetter(code);
}
}
void setup() {
pinMode(LAMP, OUTPUT);
pinMode(PIEZO, OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
Serial.begin(115200);
Serial.println("Mokxi ESP32-C3: Morse sender");
Serial.println("press the button to move to the next message");
}
void loop() {
send(MESSAGES[which]);
// a long gap, and the button read through it
unsigned long start = millis();
while (millis() - start < 1500UL) {
if (digitalRead(BUTTON) == LOW) {
which = (which + 1) % MESSAGE_COUNT;
Serial.println("next message");
while (digitalRead(BUTTON) == LOW) {
delay(10);
}
break;
}
delay(10);
}
}
Parts list
6 parts, plus the jumper wires. Every one is in the editor's parts bin.
- 1 × ESP32-C3-DevKitM-1
- 1 × Full-size breadboard
- 1 × Resistor, 220 Ω
- 1 × LED, yellow
- 1 × Piezo speaker
- 1 × Pushbutton
How it is wired
5 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Ground: ESP32-C3-DevKitM-1 pin GND; LED, yellow pin C; Piezo speaker pin 2; Pushbutton pin 2a; Pushbutton pin 2b
- ESP32-C3-DevKitM-1 pin 5; Piezo speaker pin 1
- ESP32-C3-DevKitM-1 pin 8; Resistor, 220 Ω pin 1
- ESP32-C3-DevKitM-1 pin 9; Pushbutton pin 1a; Pushbutton pin 1b
- Resistor, 220 Ω pin 2; LED, yellow pin A
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.