Parts list
| Part | Qty | Approx. | Buy |
|---|---|---|---|
| LOLIN S2 Mini | 1 | ₹350 | Buy LOLIN S2 Mini |
| HC-12 433 MHz transceiver with spring antenna | 1 | ₹350 | Buy HC-12 433 MHz transceiver with spring antenna |
| 12 mm push button | 1 | ₹10 | Buy 12 mm push button |
| 100 µF 16 V capacitor | 1 | ₹5 | Buy 100 µF 16 V capacitor |
| USB-C data cable | 1 | ₹120 | Buy USB-C data cable |
| Second HC-12 for the project you want to watch | 1 | ₹350 | Buy Second HC-12 for the project you want to watch |
| Total | ₹1,185 |
Affiliate disclosure: “Buy” links may earn FlashReady a small commission at no extra cost to you. Prices are indicative.
Wiring
| LOLIN S2 Mini | Part · pin | Wire | Notes |
|---|---|---|---|
| 37 | HC-12 433 MHz wireless serial module · TXD | green | GPIO37 → Serial1 RX (the variant’s “RX” pin, D1 mini RX position) |
| 39 | HC-12 433 MHz wireless serial module · RXD | blue | GPIO39 → Serial1 TX (the variant’s “TX” pin) |
| 40 | HC-12 433 MHz wireless serial module · SET | purple | GPIO40 — LOW = AT-command mode |
| 3V3 | HC-12 433 MHz wireless serial module · VCC | red | 100 µF capacitor across VCC/GND at the module; the S2 Mini’s regulator gives 500 mA |
| GND | HC-12 433 MHz wireless serial module · GND | black | |
| 34 | Push button (6 mm tactile switch) · 1 | yellow | GPIO34 — toggles AT mode |
| GND | Push button (6 mm tactile switch) · 2 | black |
Board quirks: The far end is any project with an HC-12 on a UART at the same baud rate (9600 by default): wire its TXD/RXD to that board’s spare serial pins and print to it instead of (or as well as) Serial. The S2 Mini’s USB-C goes straight into the ESP32-S2’s USB-OTG controller, so the laptop sees a USB serial port without any CH340/CP2102 chip — and the terminal’s baud setting doesn’t matter. The radio side is fixed at <code>RADIO_BAUD</code>. Both HC-12s must be on the same channel and air rate. The default is channel 1 (433.4 MHz), FU3, 9600 baud. In AT mode, <code>AT+RX</code> prints all settings. 433 MHz is licence-free in India only at low power. Keep <code>AT+P4</code> (+8 dBm) or lower unless you have checked the current WPC rules — range is still 100–300 m with the spring antennas, more with a proper 17 cm wire antenna in the open. HC-12 links are half-duplex and a little slow (FU3 at 9600 baud ≈ 1 kB/s): fine for text logs, not for firmware uploads.
Code
// HC-12 USB radio modem — LOLIN S2 Mini + HC-12 433 MHz transceiver.
// Plug the S2 Mini into a laptop and it becomes a wireless serial port: whatever you type in
// the Serial Monitor goes out over the HC-12, and whatever the far HC-12 sends appears on the
// laptop. Use it to watch a robot's or a field sensor's Serial output from 100+ m away.
// Press the button to toggle AT-command mode (SET LOW, LED on) and talk to the HC-12 itself:
// AT+RX shows its settings, AT+C001 sets the channel, AT+P4 sets the power.
// The ESP32-S2's own USB is the serial port, so no USB-serial chip and no baud rate to match
// on the laptop side. HC-12: TXD -> GPIO37, RXD <- GPIO39, SET <- GPIO40, VCC 3V3.
// Button: GPIO34 to GND. Blue LED (GPIO15): on in AT mode, flickers with radio traffic.
constexpr int HC_RX = 37, HC_TX = 39, HC_SET = 40, BTN = 34;
constexpr uint32_t RADIO_BAUD = 9600; // the HC-12's default (FU3); must match the far end
bool atMode = false;
uint32_t ledOffAt = 0, toRadio = 0, fromRadio = 0;
void setAt(bool on) {
atMode = on;
digitalWrite(HC_SET, on ? LOW : HIGH);
delay(on ? 60 : 100); // the HC-12 needs a moment to switch modes
if (on) Serial1.updateBaudRate(9600); // AT mode always talks at 9600
else Serial1.updateBaudRate(RADIO_BAUD);
digitalWrite(LED_BUILTIN, on ? HIGH : LOW);
Serial.println(on ? "\n[AT mode - type AT commands, e.g. AT+RX]" : "\n[radio mode]");
}
void flicker() {
if (atMode) return;
digitalWrite(LED_BUILTIN, HIGH);
ledOffAt = millis() + 20;
}
void setup() {
Serial.begin(115200); // USB CDC: the number is ignored, any terminal setting works
pinMode(HC_SET, OUTPUT);
digitalWrite(HC_SET, HIGH);
pinMode(BTN, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
Serial1.begin(RADIO_BAUD, SERIAL_8N1, HC_RX, HC_TX);
delay(1500); // give the laptop time to open the port
Serial.println("HC-12 USB radio modem ready - type to send, press the button for AT mode");
}
void loop() {
while (Serial.available()) {
char ch = Serial.read();
Serial1.write(ch);
toRadio++;
flicker();
}
while (Serial1.available()) {
Serial.write(Serial1.read());
fromRadio++;
flicker();
}
if (!atMode && ledOffAt && millis() > ledOffAt) {
digitalWrite(LED_BUILTIN, LOW);
ledOffAt = 0;
}
static bool last = HIGH;
bool b = digitalRead(BTN);
if (b == LOW && last == HIGH) {
delay(30);
setAt(!atMode);
Serial.printf("[%lu bytes sent, %lu received so far]\n", toRadio, fromRadio);
}
last = b;
}// HC-12 USB radio modem — LOLIN S2 Mini + HC-12 433 MHz transceiver.
// Plug the S2 Mini into a laptop and it becomes a wireless serial port: whatever you type in
// the Serial Monitor goes out over the HC-12, and whatever the far HC-12 sends appears on the
// laptop. Use it to watch a robot's or a field sensor's Serial output from 100+ m away.
// Press the button to toggle AT-command mode (SET LOW, LED on) and talk to the HC-12 itself:
// AT+RX shows its settings, AT+C001 sets the channel, AT+P4 sets the power.
// The ESP32-S2's own USB is the serial port, so no USB-serial chip and no baud rate to match
// on the laptop side. HC-12: TXD -> GPIO37, RXD <- GPIO39, SET <- GPIO40, VCC 3V3.
// Button: GPIO34 to GND. Blue LED (GPIO15): on in AT mode, flickers with radio traffic.
constexpr int HC_RX = 37, HC_TX = 39, HC_SET = 40, BTN = 34;
constexpr uint32_t RADIO_BAUD = 9600; // the HC-12's default (FU3); must match the far end
bool atMode = false;
uint32_t ledOffAt = 0, toRadio = 0, fromRadio = 0;
void setAt(bool on) {
atMode = on;
digitalWrite(HC_SET, on ? LOW : HIGH);
delay(on ? 60 : 100); // the HC-12 needs a moment to switch modes
if (on) Serial1.updateBaudRate(9600); // AT mode always talks at 9600
else Serial1.updateBaudRate(RADIO_BAUD);
digitalWrite(LED_BUILTIN, on ? HIGH : LOW);
Serial.println(on ? "\n[AT mode - type AT commands, e.g. AT+RX]" : "\n[radio mode]");
}
void flicker() {
if (atMode) return;
digitalWrite(LED_BUILTIN, HIGH);
ledOffAt = millis() + 20;
}
void setup() {
Serial.begin(115200); // USB CDC: the number is ignored, any terminal setting works
pinMode(HC_SET, OUTPUT);
digitalWrite(HC_SET, HIGH);
pinMode(BTN, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
Serial1.begin(RADIO_BAUD, SERIAL_8N1, HC_RX, HC_TX);
delay(1500); // give the laptop time to open the port
Serial.println("HC-12 USB radio modem ready - type to send, press the button for AT mode");
}
void loop() {
while (Serial.available()) {
char ch = Serial.read();
Serial1.write(ch);
toRadio++;
flicker();
}
while (Serial1.available()) {
Serial.write(Serial1.read());
fromRadio++;
flicker();
}
if (!atMode && ledOffAt && millis() > ledOffAt) {
digitalWrite(LED_BUILTIN, LOW);
ledOffAt = 0;
}
static bool last = HIGH;
bool b = digitalRead(BTN);
if (b == LOW && last == HIGH) {
delay(30);
setAt(!atMode);
Serial.printf("[%lu bytes sent, %lu received so far]\n", toRadio, fromRadio);
}
last = b;
}Compiled for s2mini on esp32 3.3.12 · 3 Nov 2026
How it works
Testing a line-follower on the floor, a robot in the playground, or a sensor on the water tank on the roof usually means running after it with a laptop and a long USB cable. This little dongle replaces the cable with a 433 MHz radio link. Plug it into the laptop, open any serial terminal (the Arduino Serial Monitor is fine), and the far project’s Serial output scrolls past as if it were plugged in.
The HC-12 is a cheap transceiver module built around a Silicon Labs Si4463: give it bytes on its UART and it sends them over the air; whatever it receives comes out of its TXD pin. Two HC-12s on the same channel make a transparent serial link. Here the S2 Mini simply copies bytes both ways: laptop → HC-12, and HC-12 → laptop. Its blue LED flickers with traffic.
The LOLIN S2 Mini is the right board because its ESP32-S2 has native USB: the laptop sees a USB serial port directly, with no separate USB-serial chip, and it costs about the same as a cable adapter. The HC-12 sits on Serial1, routed to the S2 Mini’s RX/TX header positions (GPIO37/39).
Press the button and the S2 pulls the HC-12’s SET pin LOW: now the laptop talks to the radio itself, so you can check and change the channel, power and air rate with AT commands (AT+RX, AT+C002, AT+P4). Press again to go back to radio mode.
Troubleshooting
Nothing comes through from the far end
Press the button and type AT+RX on both ends: channel, FU mode and baud must match. Check TXD → GPIO37 and RXD → GPIO39 (crossed, like any UART).
AT commands get no reply
The LED must be on (SET LOW). Type exactly AT and press Enter with “Newline” or “No line ending” selected; the HC-12 answers OK.
Garbled characters
The far project’s Serial1 baud rate isn’t the same as the HC-12’s (9600 by default), or the two radios use different air rates (FU modes).
Upgrades
- Add a small OLED showing bytes per second and the time since the last message.
- Timestamp every received line before printing it, for logging rooftop sensors.
- Use two of these between two laptops as a simple offline chat.



