The Telegraph: Reinvented

by amarsico_29 in Circuits > Microcontrollers

2259 Views, 21 Favorites, 0 Comments

The Telegraph: Reinvented

https___www.history.com_.image_MTU3ODc3NjU5MTU3OTk3Mjc5_this-day-in-history-01061838-morse-demonstrates-telegraph.jpg


Hi, I'm Anthony and I'm a 9th grade student at El Segundo High, this is my Reinvented telegraph. First, some history, the telegraph was a groundbreaking invention in the 1840s. It was one of the first inventions of its time that allowed near instant, long distance communication. This was a major milestone in communication because before the telegraph messages had to be physically carried by messengers on horseback or by ships. This would take anywhere from days to weeks depending on where the message was going.

In the early 1830s, inventors such as Samuel Morse started experimenting with electrical signals and sending them through wires to communicate. This led to the development of the first working telegraph system. To communicate, Morse and other inventors created a system called Morse code. This system assigned different sequences of dots and dashes to different letters and numbers to allow communication.

In 1844, the first long-distance telegraph message was sent from Washington, D.C. to Baltimore. The message famously read, “What hath God wrought,” marking the beginning of a new era in communication. These early versions of the telegraph worked by sending electrical signals through a wire between two telegraphs. This became more and more practical as time went on because more networks and stations were built to relay the signal over longer distances. This was done because over long distances the resistance in the electrical wire would weaken the signal, reducing how far the signal could travel.

The telegraph although being a revolutionary invention, its use sadly declined and became obsolete in the early 1900s due to the increasing popularity of other communication inventions such as the telephone invented by Alexander Graham Bell in 1876 or the radio which was invented by Guglielmo Marconi in the mid to late 1890s in Italy. Marconi is also credited with inventing the first practical wireless telegraph in 1895. However, this invention was only a culmination of the work of many inventors such as Nikola Tesla who had demonstrated wireless radios in St. Louis in 1893. Following this, later in 1943 an official ruling made by the U.S. Supreme Court reversed Marconi's patent and returned key radio patent rights back to Tesla.


Our Telegraph

The telegraph that we will be making in this instructable is a modernized version of the telegraph. As of right now it only works with WIFI because I wanted to create a telegraph that can work from across states and even countries. Other forms of communication with an ESP-32 would only go anywhere from a couple hundred feet to about a mile. Also most of these methods would be less effective at communication in a city due to big buildings and obstacles not offering a clear signal to the other telegraph. Therefore, I chose to run this telegraph with WIFI and an MQTT broker. It works as follows, So first we'll go over the electronics of the telegraph. So first it works by connecting to WiFi. It can auto save wifi networks on the board and re connect to them. But if there is no recognized WiFi the ESP-32 micro controller will make its own WiFi which you will then connect to with your phone. Once connected it will open a WiFI portal on your phone where you can then choose any network to connect to. After connecting to the network, the portal will be closed. Then on the telegraph it will display the message “WIFI connected.” You will then repeat these steps with the second telegraph. Then to send messages the two telegraphs will connect to an MQTT broker which is essentially a private online server. The two telegraphs will then connect onto the server using the server name and password stored in the code. Then, you will type out a message on telegraph 1 which is uploaded to the server. The other telegraph, telegraph 2 during this is constantly scanning the server for any new messages. Once a new message is detected, telegraph 2 receives it and displays it on the oled display. Using this server style communication theoretically allows the two telegraphs to talk from across the world. Although, this has not been tested. Just as long as the two telegraphs can connect to the internet they should be able to communicate with one another.

Credits to bowienewsonline.com for the introduction picture


Supplies

IMG_8897.jpg
IMG_8901.jpg
IMG_8900.jpg
IMG_8899.jpg

Supplies:

  1. 30 awg solid core copper pre-tinned wire
  2. Small magnets https://www.amazon.com/dp/B0CDLF9K2Z?ref_=ppx_hzsearch_conn_dt_b_fed_asin_title_2&th=1
  3. 2mm copper plate
  4. Different sized perfboard
  5. 1kg of 1.75mm filament (any color will work)
  6. Solder wire
  7. Proto Pasta conductive fillament
  8. Heat shrink tubing
  9. ESP-32 https://www.amazon.com/dp/B0D8T53CQ5?ref=ppx_yo2ov_dt_b_fed_asin_title
  10. Passive Buzzer https://www.amazon.com/dp/B0F1KFHSNK?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
  11. Rocker switch
  12. Buck/Boost converter https://www.amazon.com/dp/B0C69CKRWN?ref_=ppx_hzsearch_conn_dt_b_fed_asin_title_1&th=1
  13. Lipo Charge protecter https://www.amazon.com/dp/B00LTQU2RK?ref_=ppx_hzsearch_conn_dt_b_fed_asin_title_1
  14. Oled screen https://www.amazon.com/dp/B09T6SJBV5?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
  15. 1s lipo battery
  16. Knurled thumb nut https://www.amazon.com/dp/B0CWP94JBC?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
  17. m6 knurled bolt https://www.amazon.com/dp/B0CR1DMQYW?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
  18. Heat set inserts

Tools:

  1. 3d printer
  2. Soldering iron
  3. Wire strippers
  4. Tweezers
  5. Helping hands (optional but really helpful)
  6. Heat set insert tips for soldering iron
  7. Solder wick (optional but helps to remove solder if you make a mistake)
  8. Set of Allen keys
  9. Multi meter
  10. Coping saw
  11. Lighter
  12. Dremel rotary tool

Slice and Print Housing

IMG_8875.jpg

First, we want to print out our telegraph housing because printing can take about 10ish hours so while we wait for the housing to print we can work on other things. I would recommend printing the Morse code table and typing key arch both by itself because the Morse table prints best with a 0.1 nozzle and two colors whereas pretty much all the other parts are printed in a 0.2 nozzle for faster print times. Then the typing key arch is printed with Proto Pasta conductive filament. Above are my slicer settings. You will need two of each part.

The send button is already installed because I was partway into assembly when I realized I forgot to take a picture of this step.

Cut and Solder Perfboard

Next we can go ahead and cut our perfboards to size. We are starting with

Once we have the correct size perfboards we can solder our components to them to hold them in place while we solder wires on. On the ESP-32 I soldered one pin in each corner of the controller for a total of 4 pins holding the micro controller onto the board. Then, for the push button we solder two terminals that are diagonal from each other for a total of 2 terminals holding the push button to the perfboard. Do this step twice for both telegraphs.

Upload Code

Screenshot 2026-05-11 at 10.19.22 PM.png
Screenshot 2026-05-11 at 10.21.26 PM.png

Now we can take our two ESP-32s and connect them to our computer to upload the code. I am using Arduino IDE and selected ESP-32 dev board as my board in the software. You will also have to download the following libraries for this to work.

  1. <WiFi.h>
  2. <PubSubClient.h>
  3. <Wire.h>
  4. <Adafruit_GFX.h>
  5. <Adafruit_SSD1306.h>
  6. <WiFiManager.h>

After downloading these libraries, go into the sketch and find two sections. The first some should be right at the top of the sketch and it says Publish topic and Subscribe topic. On telegraph A make the publish topic telegraph/A_to_B then on the subscribe topic make it telegraph/B_to_A. Then on Telegraph B flip it. telegraph/B_to_A for the publish topic and telegraph/A_to_B for the subscribe topic. Second, scroll all the way to the bottom of the sketch where it says void connectMQTT(). Below that change ESP32Telegraph to mach each telegraph. So if you are uplading the code to telegraph A, change that to EPS32TelegraphA and vice versa for telegraph B. If this is not done your telegraphs won't be able to communicate with each other.


Code
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFiManager.h>

const char* mqtt_server = "broker.hivemq.com";
const char* publish_topic = "telegraph/A_to_B";
const char* subscribe_topic = "telegraph/B_to_A";

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_ADDR_PRIMARY 0x3C
#define OLED_ADDR_FALLBACK 0x3D
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const int keyPin = 12;
const int clearPin = 14;
const int buzzerPin = 27;

const char* morseSymbols[] = {
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---",
"-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-",
"..-", "...-", ".--", "-..-", "-.--", "--..",
"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."
};

const char letters[] = {
'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','0','1','2','3','4','5','6','7','8','9'
};

WiFiClient espClient;
PubSubClient client(espClient);

char currentMorse[10] = {0};
char currentMessage[64] = {0};

unsigned long keyPressTime = 0;
unsigned long lastReleaseTime = 0;
unsigned long lastClearPressTime = 0;
bool clearPressPending = false;

// Timing
const unsigned long dotThreshold = 300; // under 400 ms = dot
const unsigned long dashThreshold = 600; // 300 ms to under 600 ms = dash
const unsigned long letterGap = 800; // 600 ms to 800ms = finish letter
const unsigned long debounceDelay = 30; // ignore switch bounce
const unsigned long doubleClickGap = 500; // two quick clear-button presses = clear

void connectMQTT();
void mqttCallback(char* topic, byte* payload, unsigned int length);
char decodeMorse(const char* morseSymbol);
bool initDisplay();

void setup() {
Serial.begin(115200);

pinMode(keyPin, INPUT_PULLUP);
pinMode(clearPin, INPUT_PULLUP);
pinMode(buzzerPin, OUTPUT);

ledcAttach(buzzerPin, 1000, 8);

Wire.begin(OLED_SDA, OLED_SCL);

if (!initDisplay()) {
Serial.println("OLED failed to initialize. Check VCC, GND, SDA, SCL, and I2C address.");
while (true) {
delay(100);
}
}

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Telegraph Starting...");
display.display();

WiFiManager wm;
bool ok = wm.autoConnect("Telegraph-Setup");

if (!ok) {
Serial.println("Failed to connect");
display.clearDisplay();
display.setCursor(0, 0);
display.println("WiFi failed");
display.display();
} else {
Serial.println("WiFi connected");
display.clearDisplay();
display.setCursor(0, 0);
display.println("WiFi connected");
display.display();
}

client.setServer(mqtt_server, 1883);
client.setCallback(mqttCallback);
}

bool initDisplay() {
Wire.beginTransmission(OLED_ADDR_PRIMARY);
if (Wire.endTransmission() == 0) {
Serial.println("OLED found at 0x3C");
return display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR_PRIMARY);
}

Wire.beginTransmission(OLED_ADDR_FALLBACK);
if (Wire.endTransmission() == 0) {
Serial.println("OLED found at 0x3D");
return display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR_FALLBACK);
}

Serial.println("No OLED detected on I2C at 0x3C or 0x3D");
return false;
}

void loop() {
if (!client.connected()) {
connectMQTT();
}
client.loop();

static bool lastRawKeyState = HIGH;
static bool stableKeyState = HIGH;
static unsigned long lastDebounceTime = 0;

unsigned long now = millis();
bool rawKeyState = digitalRead(keyPin);

if (rawKeyState != lastRawKeyState) {
lastDebounceTime = now;
lastRawKeyState = rawKeyState;
}

if ((now - lastDebounceTime) > debounceDelay) {
if (rawKeyState != stableKeyState) {
stableKeyState = rawKeyState;

if (stableKeyState == LOW) {
keyPressTime = now;
ledcWriteTone(buzzerPin, 1000);
} else {
if (keyPressTime != 0) {
unsigned long pressDuration = now - keyPressTime;
keyPressTime = 0;
ledcWriteTone(buzzerPin, 0);

if (pressDuration >= dashThreshold) {
int msgLen = strlen(currentMessage);
if (msgLen < (int)sizeof(currentMessage) - 1 &&
(msgLen == 0 || currentMessage[msgLen - 1] != ' ')) {
currentMessage[msgLen] = ' ';
currentMessage[msgLen + 1] = '\0';
}

currentMorse[0] = '\0';

display.clearDisplay();
display.setCursor(0, 0);
display.println(currentMessage);
display.display();
} else {
int len = strlen(currentMorse);
if (len < (int)sizeof(currentMorse) - 1) {
if (pressDuration < dotThreshold) {
currentMorse[len] = '.';
} else {
currentMorse[len] = '-';
}
currentMorse[len + 1] = '\0';
}

lastReleaseTime = now;

display.clearDisplay();
display.setCursor(0, 0);
display.println(currentMessage);
display.println(currentMorse);
display.display();
}
}
}
}
}

if (strlen(currentMorse) > 0 && now - lastReleaseTime > letterGap) {
char letter = decodeMorse(currentMorse);

int msgLen = strlen(currentMessage);
if (msgLen < (int)sizeof(currentMessage) - 1) {
currentMessage[msgLen] = letter;
currentMessage[msgLen + 1] = '\0';
}

currentMorse[0] = '\0';

display.clearDisplay();
display.setCursor(0, 0);
display.println(currentMessage);
display.display();

}

if (digitalRead(clearPin) == LOW) {
delay(50);
if (digitalRead(clearPin) == LOW) {
while (digitalRead(clearPin) == LOW) {
delay(10);
}

unsigned long pressTime = millis();
if (clearPressPending && (pressTime - lastClearPressTime) <= doubleClickGap) {
clearPressPending = false;
currentMessage[0] = '\0';
currentMorse[0] = '\0';

display.clearDisplay();
display.setCursor(0, 0);
display.println("Message cleared.");
display.display();

delay(1000);

display.clearDisplay();
display.setCursor(0, 0);
display.println(currentMessage);
display.display();
} else {
clearPressPending = true;
lastClearPressTime = pressTime;
}
}
}

if (clearPressPending && (millis() - lastClearPressTime) > doubleClickGap) {
clearPressPending = false;

if (strlen(currentMessage) > 0) {
client.publish(publish_topic, currentMessage, true);

display.clearDisplay();
display.setCursor(0, 0);
display.println("Sent:");
display.println(currentMessage);
display.display();

currentMessage[0] = '\0';
currentMorse[0] = '\0';
} else {
display.clearDisplay();
display.setCursor(0, 0);
display.println("No message to send");
display.display();
}

delay(1000);

display.clearDisplay();
display.setCursor(0, 0);
display.println(currentMessage);
if (strlen(currentMorse) > 0) {
display.println(currentMorse);
}
display.display();
}
}

char decodeMorse(const char* morseSymbol) {
Serial.print("Decoding: ");
Serial.println(morseSymbol);

for (int i = 0; i < 36; i++) {
if (strcmp(morseSymbol, morseSymbols[i]) == 0) {
return letters[i];
}
}

Serial.println("Unknown Morse pattern");
return '?';
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
char msg[64];

if (length >= sizeof(msg)) {
length = sizeof(msg) - 1;
}

memcpy(msg, payload, length);
msg[length] = '\0';

display.clearDisplay();
display.setCursor(0, 0);
display.println("Received:");
display.println(msg);
display.display();
}

void connectMQTT() {
while (!client.connected()) {
if (client.connect("ESP32TelegraphA")) {
client.subscribe(subscribe_topic);
} else {
delay(2000);
}
}
}



Solder the ESP, Charging Module, and Components

IMG_8894.jpg

Now we can solder the entire board. I would start by soldering the ground and power pads on each side of the perfboard before starting anything else. Once this has been done solder all of the wires that are connecting to the ESP-32. Don't solder the components to the wire then to the board. It will make it a little bit harder to do and you won't be able to put the buzzer in its holder. Instead, solder each wire to its respective pin, ground, or power pads. Then once all of the wires have been soldered to the ESP you can connect the wires to the OLED display and push button. For our buzzer, slide the buzzer inside of the 3d printed buzzer holder and then solder the wires onto the buzzer once it is inserted into the holder. (don't be alarmed, the fit of the buzzer housing is extremely tight so don't be afraid to use some force to get it into the holder) Above I provided a diagram of how everything should be wired. Once every component has been soldered to their respective wire you can now slide the buzzer inside of the buzzer holder and solder on the power and ground wires. Above is a picture showing how it should be installed. Also this is not mandatory but if you would like you can plug in a battery or power the circuit from your computer and see if everything works.

Note: For the buck/boost converter in the charging circuit, make sure it is tuned to 5v. If this is not done and the circuit is turned on it could fry the ESP-32


Charging circuit

Lipo Battery

  1. (+) --> Lipo charge protector (B+)
  2. (-) --> Lipo charge protector (B-)

Lipo charge protector

  1. Out (+) --> Rocker switch (+)
  2. Rocker switch (-) --> Buck/Boost converter Vin (+)
  3. Out (-) --> Buck/Boost converter Vin (-)

Buck/Boost converter

  1. Out (+) --> Perf-board power rail
  2. Out (-) --> Perf-board ground rail


ESP-32 circuit Wiring

  1. GND pin --> Perf-board ground rail
  2. VN pin --> Perf-board power rail
  3. D14 pin --> Push button (+)
  4. D21 pin --> Oled display (SDA pin)
  5. D22 pin --> Oled display (SCL pin)
  6. D27 pin --> Oled display (Passive buzzer +)
  7. D12 pin --> Typing key wire

Pushbutton

  1. (-) --> Perf-board ground rail

Passive buzzer

  1. (-) --> Perf-board ground rail

I2C Oled display

  1. VCC --> Perf-board power rail
  2. GND --> Perf-board ground rail

Typing key

  1. Key --> Perf-board power rail

Heat Set Inserts

IMG_8866.jpg
IMG_8867.jpg
IMG_8868.jpg
IMG_8870.jpg
IMG_8873.jpg
IMG_8874.jpg

Once we have all of our components soldered together we can now grab our 3d printed parts and prep them for assembly. Ensure all support material has been removed before installing heat set inserts. Now we can take our m2 heat set inserts and place them all around our housing like in the pictures above. Then for the typing key arch (black part) we use m5 heat set inserts on the two legs then an m6 heat set insert on the top of the arch.

Note: Try to keep the inserts as straight as possible when inserting to make assembly easier. It's okay if it's not completely straight but just try your best.

Installing Components

IMG_8871.jpg
IMG_8872.jpg
IMG_8876.jpg
IMG_8877.jpg
IMG_8880.jpg
IMG_8879.jpg
IMG_8878.jpg
IMG_8895.jpg

Now we can take our m2 screw and start installing our electrical components into our housing. Start with the biggest to smallest components. I would recommend installing the push button first (put the send button in first then install the push button), then the ESP-32, followed by the OLED display, buzzer, rocker switch, and the typing key wires (I used 26 awg stranded silicone copper wire for the typing key wire). After this has been done, you can take the 2mm copper plate and cut it into a rectangle approximately 11mm x 21mm with a coping saw. I used a coping saw because it's easier to cut smaller designs but almost any saw or cutter will do the job. Next, mark the bolt holes on the copper so you know where to drill your 2mm bolt holes. To install the handle for the back pannel door, cut two m2 bolts to about 15mm long to screw the handle onto the back door.

How to Install the Typing Key

IMG_8884.jpg
IMG_8886.jpg
IMG_8885.jpg

Run the wire up through the hole in the bottom of the telegraph and then through the telegraph key. The wire should sit in between the plastic typing key and the copper plate. This is done so the wire is sandwiched and has a good connection to the copper plate to transmit the electrical signal. Above is an example of what it should look like. Next is the weight. Cut the bolt head off of an m6 bolt then tread it onto one of the knurled thumb nuts. Next, slide it into the big hole on the typing key. Finally cut an m2 bolt to about 30mm long to mount the typing key to the telegraph. To secure it, use an m2 nut and screw it in on the other side like in the picture above.

Note: If the key is lose you can slide a washer in between the typing key and the typing key mount to remove some of the slop.

Installing Magnets

IMG_8888.jpg
IMG_8889.jpg
IMG_8890.jpg
IMG_8891.jpg

After all of the heat set inserts are added we can take our magnets and start pressing them into the magnet holes all around the telegraph housing. Above are pictures showing where every magnet should go. If needed, you can add a drop of super glue inside a magnet hole to better secure the magnet if it's too loose. Here I was using 4mm x 2mm circle magnets.

Note: The magnets will have a very tight tolerance so they don't come out. Therefore it requires a substantial amount of force to press the magnets into place.

Typing Key Arch

IMG_8881.jpg

Now we can install the typing key arch. We first use an m5 bolt and one washer to secure either one of the legs down. But only one, don't do this for both. Now, on the second leg we will take an m5 bolt and two washers and wrap the second typing key wire around the bolt. Finally, tighten down the bolt with the two washers to sandwich the wire in between. The picture above shows how its done.

Test

Once both telegraphs have been assembled and a battery is connected, turn the telegraph on by flipping the toggle switches. When the screen turns on a message will show stating "telegraph starting." When this screen appears, open your phones WIFI and look for a WIFI called Telegraph Setup. Click on this WIFI and it will bring you to a portal where you can select your home WIFI and input the password. After that, the portal will automatically close and the telegraph will be connected. This needs to be done for both telegraphs. The good thing though is that the telegraph will auto save the WIFI so you wont have to do this again unless you want to connect to a different WIFI network. Congratulations! You should now have a working telegraph system.

Cool Features and How to Use.

IMG_8906.jpg

Features

  1. Message memory (saves the last message received when the telegraph is off)
  2. Auto decoding (decodes the Morse and turns it into words)
  3. Built in Morse table (Morse table lets you send messages without needing to remember Morse code)

How to use

First you will type out a morse sequence on the typer/long key. That message is then displayed on the screen first in morse so you can see what you're writing and then it is decoded and written in letters. Once you are done with your message, you press the send button to send the message to the server. If you mess up a message, you can double press the send button to clear the message and restart.