How to transmit and receive raw data from a microcontroller to a remote computer?

 Here’s a practical, no-fluff roadmap for sending raw bytes between a microcontroller and a remote computer (over the internet).



1) Pick your transport

  • Direct IP from the MCU: MCU with Ethernet/Wi-Fi (e.g., ESP32, W5500, NINA) → TCP or UDP sockets to a public server.

  • Via a gateway: MCU talks UART/USB to a Raspberry Pi (or similar), and the Pi forwards data over TCP/UDP/SSH/VPN.

  • Cellular/LPWAN: Use LTE-M/NB-IoT modem (PPP/AT or built-in sockets). Same socket idea, just different link.

Tip: Inbound connections to a device behind NAT are painful. Easiest: host a public server (cloud VM) and have the MCU dial out to it.

2) Frame your “raw” bytes

Raw ≠ structureless. Use a tiny frame so both sides can parse:

[0xAA 0x55] [LEN(2B)] [PAYLOAD (LEN bytes)] [CRC16(2B)]

Or simpler: [LEN][PAYLOAD]. If you stream without length, at least add a delimiter (e.g., '\n') and escape it when it appears in data.

3) Reliability & security

  • TCP gives ordered, reliable bytes (most common).

  • UDP is lighter/low-latency, but add sequence numbers, ACK/timeout if you need reliability.

  • Security: Use TLS (client → server). If TLS on MCU is heavy, terminate TLS on the server (e.g., stunnel/Nginx “stream”) and keep the MCU→server hop inside a VPN (e.g., WireGuard).

4) Minimal working example (TCP)

A) Remote computer (server) — Python 3

# server.py (listens on 0.0.0.0:5000) import socket, struct def recv_all(sock, n): data = b"" while len(data) < n: chunk = sock.recv(n - len(data)) if not chunk: return None data += chunk return data with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(("", 5000)) s.listen(1) print("Listening on :5000") conn, addr = s.accept() print("Client:", addr) with conn: while True: hdr = recv_all(conn, 2) # 2-byte length if not hdr: break (length,) = struct.unpack("!H", hdr) # network byte order payload = recv_all(conn, length) if payload is None: break # Do something with raw bytes: print("Got", length, "bytes:", payload.hex()) # Echo back (optional): conn.sendall(struct.pack("!H", len(payload)) + payload)

B) Microcontroller (client) — ESP32 (Arduino)

#include <WiFi.h> const char* ssid = "YOUR_SSID"; const char* pass = "YOUR_PASS"; const char* host = "YOUR_SERVER_IP_OR_DNS"; const uint16_t port = 5000; WiFiClient client; void sendFrame(const uint8_t* data, uint16_t len) { uint8_t hdr[2] = { (uint8_t)(len >> 8), (uint8_t)(len & 0xFF) }; client.write(hdr, 2); client.write(data, len); } void setup() { Serial.begin(115200); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) delay(200); if (!client.connect(host, port)) { while (1) { delay(1000); } } // Example payload: 2 bytes sensor, 4 bytes counter (big-endian) static uint32_t counter = 0; uint8_t payload[6]; uint16_t sensor = 1234; // demo payload[0] = sensor >> 8; payload[1] = sensor & 0xFF; payload[2] = (counter >> 24) & 0xFF; payload[3] = (counter >> 16) & 0xFF; payload[4] = (counter >> 8) & 0xFF; payload[5] = (counter) & 0xFF; sendFrame(payload, sizeof(payload)); counter++; } void loop() { // Read echo (optional) while (client.available() >= 2) { uint16_t len = (client.read() << 8) | client.read(); while (client.available() < len) ; // simple demo; add timeout in real code for (uint16_t i=0;i<len;i++) (void)client.read(); // consume } delay(1000); }

No Wi-Fi/Ethernet on your MCU? Connect its UART to a Raspberry Pi and run a serial-to-socket bridge (e.g., ser2net), or write a tiny Python script on the Pi that reads /dev/ttyAMA0 and forwards to your TCP server.

5) UDP variant (when you control both ends)

  • MCU: sendto(serverIP, port, payload).

  • PC: Python socket.socket(AF_INET, SOCK_DGRAM)recvfrom.
    Add [SEQ][PAYLOAD][CRC]; the PC can ACK sequence SEQ back so the MCU retries on timeout.

6) NAT traversal options

  • Put the Python server on a public VM (recommended).

  • Or set up WireGuard between MCU’s gateway (Pi) and your PC.

  • Or use reverse SSH tunnel from a Pi:
    ssh -N -R 5000:localhost:5000 user@public-host (then the MCU connects to public-host:5000 locally on the Pi).

7) Practical checklist

  • Fixed endianness (use big-endian/network order), and document it.

  • Length-prefix frames; add CRC16 if you want quick integrity checks.

  • Keep-alive (TCP): send a short heartbeat every few seconds; detect disconnects.

  • Backpressure: use ring buffers; don’t block ISR/context.

  • Time sync if needed (NTP from MCU or gateway).

  • Throughput targets: choose TCP for reliability, UDP for low jitter.

评论

此博客中的热门博文

Detailed Explanation of STM32 HAL Library Clock System

How To Connect Stm32 To PC?

How do you set up ADC (Analog-to-Digital Converter) in STM32?