This Arduino library implements a direct Point-to-Point Protocol (PPP) connection between an ESP32 and a host via UART. Unlike IDF PPPoS examples that require a GSM modem, it can establish a direct serial connection to a Linux machine natively supporting PPP, leveraging its routing and NAT capabilities to provide network connectivity to the ESP32.
This library seamlessly integrates with ESP32's native TCP/IP stack, making the PPP connection appear as a standard network interface (similar to WiFi or Ethernet). It is possible to use the familiar Arduino networking APIs (NetworkClient
, etc.) and popular libraries like ESPAsyncWebServer
without any modifications.
A cool feature is the ability to expose the ESP32 securely to the Internet through Tailscale running on the Linux host. This provides a simple yet secure way to create remotely accessible IoT devices without complex VPN setups or cloud service dependencies.
This code builds upon the concepts from ESP32-PPPos-TLS by hussainhadi673, reimplemented as a standalone Arduino library without TLS. For most remote control use cases, the security can be implemented on the host side (e.g. Tailscale's encrypted mesh network), eliminating the need for additional TLS overhead.
- ESP32 MCU
- Arduino Core ESP32 v3.0.0 or higher
- Linux host machine
- UART connection between ESP32 and Linux host
- Clone or download the library (
lib/DPPPoS
) to your Arduino project'slib
directory - Include the header in your project & declare an instance of the
DPPPoS
class:
#include "DPPPoS.h"
DPPPoS PPPoS;
- Connect ESP32's UART
TX
pin to Linux host'sRX
- Connect ESP32's UART
RX
pin to Linux host'sTX
- Connect ESP32's
GND
to Linux host'sGND
#define UART_TX_PIN D7
#define UART_RX_PIN D6
#define UART_BAUDRATE 115200
// Configure Serial1 for PPPoS with improved buffer sizes
// (2048 by default, useful as the default PPP MTU is 1500)
Serial1.setTxBufferSize(DPPPoS::UART_TX_BUFFER_SIZE);
Serial1.setRxBufferSize(DPPPoS::UART_RX_BUFFER_SIZE);
Serial1.begin(115200, SERIAL_8N1, UART_RX_PIN, UART_TX_PIN);
// Optional: Custom IP configuration
PPPoSClass::IPConfig config = {
.gateway = IPAddress(10, 0, 0, 1), // PPP Gateway IP
.dns = IPAddress(8, 8, 8, 8) // DNS Server
};
// Initialize PPPoS
if (!PPPoS.begin(Serial1, &config)) {
Serial.println("PPPoS initialization failed");
while (true) delay(1000);
}
No call to PPPoS.loop()
is required in your code, PPP data is automatically sent and received in the background by the LoopTask
task (for better performance it can be pinned to core 0 if required).
void loop() {
if (PPPoS.connected()) {
// Your network code here
} else {
// You can handle disconnection here
Serial.println("Waiting for PPP connection...");
delay(1000);
}
}
Refer to the linux/setup.sh
script for guidelines on :
- Setting up the PPP connection
- Enabling internet access from the ESP32
- Routing external traffic to the ESP32
The library allows transparent use of ESP32's TCP/IP stack. Example using a network client:
NetworkClient client;
if (client.connect("google.com", 80)) {
client.println("GET / HTTP/1.0");
client.println("Host: google.com");
client.println();
while (client.connected()) {
if (client.available()) {
String line = client.readStringUntil('\n');
Serial.println(line);
}
}
client.stop();
}
Compatible with ESPAsyncWebServer
for creating a web interface serving files or an HTTP API:
AsyncWebServer server(80);
void setup() {
// PPPoS initialization...
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", "Hello World");
});
server.begin();
}
- src/main.cpp provides a minimal example of using the library with custom IP configuration
- examples/main.cpp provides an example of using the library to send HTTP GET requests to local and remote machines (Linux host + google.com) and exposes a basic web page to show performance metrics (GET request RTT). Follow instructions in the
setup.sh
script to setup the Python server on the host that will reply to GET requests + upload filesystem to ESP32 flash to get access to the web page.
Enable debug output by defining PPPOS_DEBUG
(e.g. in your platformio.ini
file):
build_flags = -D PPPOS_DEBUG
This will output detailed connection information and data hexdumps.
The library manages the following connection states:
CONNECTED
: Successfully connected to the networkCONNECTING
: Connection attempt in progressCONNECTION_LOST
: Connection lost, will attempt reconnectionDISCONNECTED
: Disconnected from network
A dedicated task (NetWatchdogTask
) monitors the connection status and attempts reconnection if the connection is lost.
MIT License