Skip to content

Add support for PPP Modems to Arduino #9518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ set(ARDUINO_ALL_LIBRARIES
LittleFS
NetBIOS
Network
PPP
Preferences
RainMaker
SD_MMC
Expand Down Expand Up @@ -157,6 +158,10 @@ set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp)

set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp)

set(ARDUINO_LIBRARY_PPP_SRCS
libraries/PPP/src/PPP.cpp
libraries/PPP/src/ppp.c)

set(ARDUINO_LIBRARY_Preferences_SRCS libraries/Preferences/src/Preferences.cpp)

set(ARDUINO_LIBRARY_RainMaker_SRCS
Expand Down
10 changes: 10 additions & 0 deletions Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,16 @@ config ARDUINO_SELECTIVE_Networking
depends on ARDUINO_SELECTIVE_COMPILATION
default y

config ARDUINO_SELECTIVE_Ethernet
bool "Enable Ethernet"
depends on ARDUINO_SELECTIVE_COMPILATION
default y

config ARDUINO_SELECTIVE_PPP
bool "Enable PPP"
depends on ARDUINO_SELECTIVE_COMPILATION
default y

config ARDUINO_SELECTIVE_ArduinoOTA
bool "Enable ArduinoOTA"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
Expand Down
6 changes: 6 additions & 0 deletions cores/esp32/esp32-hal-periman.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ const char* perimanGetTypeName(peripheral_bus_type_t type) {
case ESP32_BUS_TYPE_ETHERNET_MCD: return "ETHERNET_MCD";
case ESP32_BUS_TYPE_ETHERNET_MDIO: return "ETHERNET_MDIO";
case ESP32_BUS_TYPE_ETHERNET_PWR: return "ETHERNET_PWR";
#endif
#if CONFIG_LWIP_PPP_SUPPORT
case ESP32_BUS_TYPE_PPP_TX: return "PPP_MODEM_TX";
case ESP32_BUS_TYPE_PPP_RX: return "PPP_MODEM_RX";
case ESP32_BUS_TYPE_PPP_RTS: return "PPP_MODEM_RTS";
case ESP32_BUS_TYPE_PPP_CTS: return "PPP_MODEM_CTS";
#endif
default: return "UNKNOWN";
}
Expand Down
6 changes: 6 additions & 0 deletions cores/esp32/esp32-hal-periman.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ extern "C" {
ESP32_BUS_TYPE_ETHERNET_MCD, // IO is used as ETHERNET MCD pin
ESP32_BUS_TYPE_ETHERNET_MDIO, // IO is used as ETHERNET MDIO pin
ESP32_BUS_TYPE_ETHERNET_PWR, // IO is used as ETHERNET PWR pin
#endif
#if CONFIG_LWIP_PPP_SUPPORT
ESP32_BUS_TYPE_PPP_TX, // IO is used as PPP Modem TX pin
ESP32_BUS_TYPE_PPP_RX, // IO is used as PPP Modem RX pin
ESP32_BUS_TYPE_PPP_RTS, // IO is used as PPP Modem RTS pin
ESP32_BUS_TYPE_PPP_CTS, // IO is used as PPP Modem CTS pin
#endif
ESP32_BUS_TYPE_MAX
} peripheral_bus_type_t;
Expand Down
1 change: 1 addition & 0 deletions idf_component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ dependencies:
idf: ">=5.1"
# mdns 1.2.1 is necessary to build H2 with no WiFi
mdns: "^1.2.3"
espressif/esp_modem: "^1.1.0"
chmorgan/esp-libhelix-mp3:
version: "1.0.3"
require: public
Expand Down
18 changes: 8 additions & 10 deletions libraries/Network/src/NetworkEvents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,16 +319,14 @@ const char *NetworkEvents::eventName(arduino_event_id_t id) {
case ARDUINO_EVENT_ETH_DISCONNECTED: return "ETH_DISCONNECTED";
case ARDUINO_EVENT_ETH_GOT_IP: return "ETH_GOT_IP";
case ARDUINO_EVENT_ETH_LOST_IP: return "ETH_LOST_IP";
case ARDUINO_EVENT_ETH_GOT_IP6:
return "ETH_GOT_IP6";

// case ARDUINO_EVENT_PPP_START: return "PPP_START";
// case ARDUINO_EVENT_PPP_STOP: return "PPP_STOP";
// case ARDUINO_EVENT_PPP_CONNECTED: return "PPP_CONNECTED";
// case ARDUINO_EVENT_PPP_DISCONNECTED: return "PPP_DISCONNECTED";
// case ARDUINO_EVENT_PPP_GOT_IP: return "PPP_GOT_IP";
// case ARDUINO_EVENT_PPP_LOST_IP: return "PPP_LOST_IP";
// case ARDUINO_EVENT_PPP_GOT_IP6: return "PPP_GOT_IP6";
case ARDUINO_EVENT_ETH_GOT_IP6: return "ETH_GOT_IP6";
case ARDUINO_EVENT_PPP_START: return "PPP_START";
case ARDUINO_EVENT_PPP_STOP: return "PPP_STOP";
case ARDUINO_EVENT_PPP_CONNECTED: return "PPP_CONNECTED";
case ARDUINO_EVENT_PPP_DISCONNECTED: return "PPP_DISCONNECTED";
case ARDUINO_EVENT_PPP_GOT_IP: return "PPP_GOT_IP";
case ARDUINO_EVENT_PPP_LOST_IP: return "PPP_LOST_IP";
case ARDUINO_EVENT_PPP_GOT_IP6: return "PPP_GOT_IP6";
#if SOC_WIFI_SUPPORTED
case ARDUINO_EVENT_WIFI_OFF: return "WIFI_OFF";
case ARDUINO_EVENT_WIFI_READY: return "WIFI_READY";
Expand Down
15 changes: 8 additions & 7 deletions libraries/Network/src/NetworkEvents.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ typedef enum {
ARDUINO_EVENT_PROV_CRED_FAIL,
ARDUINO_EVENT_PROV_CRED_SUCCESS,
#endif
// ARDUINO_EVENT_PPP_START,
// ARDUINO_EVENT_PPP_STOP,
// ARDUINO_EVENT_PPP_CONNECTED,
// ARDUINO_EVENT_PPP_DISCONNECTED,
// ARDUINO_EVENT_PPP_GOT_IP,
// ARDUINO_EVENT_PPP_LOST_IP,
// ARDUINO_EVENT_PPP_GOT_IP6,
ARDUINO_EVENT_PPP_START,
ARDUINO_EVENT_PPP_STOP,
ARDUINO_EVENT_PPP_CONNECTED,
ARDUINO_EVENT_PPP_DISCONNECTED,
ARDUINO_EVENT_PPP_GOT_IP,
ARDUINO_EVENT_PPP_LOST_IP,
ARDUINO_EVENT_PPP_GOT_IP6,
ARDUINO_EVENT_MAX
} arduino_event_id_t;

Expand Down Expand Up @@ -146,6 +146,7 @@ class NetworkEvents {

friend class ESP_NetworkInterface;
friend class ETHClass;
friend class PPPClass;
#if SOC_WIFI_SUPPORTED
friend class STAClass;
friend class APClass;
Expand Down
42 changes: 19 additions & 23 deletions libraries/Network/src/NetworkInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,11 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data) {
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP;
} else
#endif
// if(_interface_id == ESP_NETIF_ID_PPP){
// arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP;
// } else
if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP;
}
if (_interface_id == ESP_NETIF_ID_PPP) {
arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP;
} else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP;
}
} else if (event_id == _lost_ip_event_id) {
clearStatusBits(ESP_NETIF_HAS_IP_BIT);
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
Expand All @@ -87,12 +86,11 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data) {
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_LOST_IP;
} else
#endif
// if(_interface_id == ESP_NETIF_ID_PPP){
// arduino_event.event_id = ARDUINO_EVENT_PPP_LOST_IP;
// } else
if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
arduino_event.event_id = ARDUINO_EVENT_ETH_LOST_IP;
}
if (_interface_id == ESP_NETIF_ID_PPP) {
arduino_event.event_id = ARDUINO_EVENT_PPP_LOST_IP;
} else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
arduino_event.event_id = ARDUINO_EVENT_ETH_LOST_IP;
}
} else if (event_id == IP_EVENT_GOT_IP6) {
ip_event_got_ip6_t* event = (ip_event_got_ip6_t*)event_data;
esp_ip6_addr_type_t addr_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
Expand All @@ -117,12 +115,11 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data) {
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_GOT_IP6;
} else
#endif
// if(_interface_id == ESP_NETIF_ID_PPP){
// arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP6;
// } else
if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP6;
}
if (_interface_id == ESP_NETIF_ID_PPP) {
arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP6;
} else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP6;
}
#if SOC_WIFI_SUPPORTED
} else if (event_id == IP_EVENT_AP_STAIPASSIGNED && _interface_id == ESP_NETIF_ID_AP) {
setStatusBits(ESP_NETIF_HAS_IP_BIT);
Expand Down Expand Up @@ -536,7 +533,7 @@ String NetworkInterface::impl_name(void) const {
char netif_name[8];
esp_err_t err = esp_netif_get_netif_impl_name(_esp_netif, netif_name);
if (err != ESP_OK) {
log_e("Failed to get netif impl_name: %d", err);
log_e("Failed to get netif impl_name: 0x%04x %s", err, esp_err_to_name(err));
return String("");
}
return String(netif_name);
Expand All @@ -562,7 +559,7 @@ bool NetworkInterface::setDefault() {
}
esp_err_t err = esp_netif_set_default_netif(_esp_netif);
if (err != ESP_OK) {
log_e("Failed to set default netif: %d", err);
log_e("Failed to set default netif: 0x%04x %s", err, esp_err_to_name(err));
return false;
}
return true;
Expand All @@ -576,15 +573,14 @@ bool NetworkInterface::isDefault() const {
}

uint8_t* NetworkInterface::macAddress(uint8_t* mac) const {
if (!mac || _esp_netif == NULL) {
if (!mac || _esp_netif == NULL || _interface_id == ESP_NETIF_ID_PPP) {
return NULL;
}
esp_err_t err = esp_netif_get_mac(_esp_netif, mac);
if (err != ESP_OK) {
log_e("Failed to get netif mac: %d", err);
log_e("Failed to get netif mac: 0x%04x %s", err, esp_err_to_name(err));
return NULL;
}
// getMac(mac);
return mac;
}

Expand Down
141 changes: 141 additions & 0 deletions libraries/PPP/examples/PPP_Basic/PPP_Basic.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include <PPP.h>

#define PPP_MODEM_APN "internet"
#define PPP_MODEM_PIN "0000" // or NULL

// WaveShare SIM7600 HW Flow Control
#define PPP_MODEM_RST 25
#define PPP_MODEM_RST_LOW false //active HIGH
#define PPP_MODEM_TX 21
#define PPP_MODEM_RX 22
#define PPP_MODEM_RTS 26
#define PPP_MODEM_CTS 27
#define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_HW
#define PPP_MODEM_MODEL PPP_MODEM_SIM7600

// SIM800 basic module with just TX,RX and RST
// #define PPP_MODEM_RST 0
// #define PPP_MODEM_RST_LOW true //active LOW
// #define PPP_MODEM_TX 2
// #define PPP_MODEM_RX 19
// #define PPP_MODEM_RTS -1
// #define PPP_MODEM_CTS -1
// #define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_NONE
// #define PPP_MODEM_MODEL PPP_MODEM_SIM800

void onEvent(arduino_event_id_t event, arduino_event_info_t info) {
switch (event) {
case ARDUINO_EVENT_PPP_START:
Serial.println("PPP Started");
break;
case ARDUINO_EVENT_PPP_CONNECTED:
Serial.println("PPP Connected");
break;
case ARDUINO_EVENT_PPP_GOT_IP:
Serial.println("PPP Got IP");
break;
case ARDUINO_EVENT_PPP_LOST_IP:
Serial.println("PPP Lost IP");
break;
case ARDUINO_EVENT_PPP_DISCONNECTED:
Serial.println("PPP Disconnected");
break;
case ARDUINO_EVENT_PPP_STOP:
Serial.println("PPP Stopped");
break;
default:
break;
}
}

void testClient(const char* host, uint16_t port) {
NetworkClient client;
if (!client.connect(host, port)) {
Serial.println("Connection Failed");
return;
}
client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
while (client.connected() && !client.available())
;
while (client.available()) {
client.read(); //Serial.write(client.read());
}

Serial.println("Connection Success");
client.stop();
}

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

// Listen for modem events
Network.onEvent(onEvent);

// Configure the modem
PPP.setApn(PPP_MODEM_APN);
PPP.setPin(PPP_MODEM_PIN);
PPP.setResetPin(PPP_MODEM_RST, PPP_MODEM_RST_LOW);
PPP.setPins(PPP_MODEM_TX, PPP_MODEM_RX, PPP_MODEM_RTS, PPP_MODEM_CTS, PPP_MODEM_FC);

Serial.println("Starting the modem. It might take a while!");
PPP.begin(PPP_MODEM_MODEL);

Serial.print("Manufacturer: ");
Serial.println(PPP.cmd("AT+CGMI", 10000));
Serial.print("Model: ");
Serial.println(PPP.moduleName());
Serial.print("IMEI: ");
Serial.println(PPP.IMEI());

bool attached = PPP.attached();
if (!attached) {
int i = 0;
unsigned int s = millis();
Serial.print("Waiting to connect to network");
while (!attached && ((++i) < 600)) {
Serial.print(".");
delay(100);
attached = PPP.attached();
}
Serial.print((millis() - s) / 1000.0, 1);
Serial.println("s");
attached = PPP.attached();
}

Serial.print("Attached: ");
Serial.println(attached);
Serial.print("State: ");
Serial.println(PPP.radioState());
if (attached) {
Serial.print("Operator: ");
Serial.println(PPP.operatorName());
Serial.print("IMSI: ");
Serial.println(PPP.IMSI());
Serial.print("RSSI: ");
Serial.println(PPP.RSSI());
int ber = PPP.BER();
if (ber > 0) {
Serial.print("BER: ");
Serial.println(ber);
Serial.print("NetMode: ");
Serial.println(PPP.networkMode());
}

Serial.println("Switching to data mode...");
PPP.mode(ESP_MODEM_MODE_CMUX); // Data and Command mixed mode
if (!PPP.waitStatusBits(ESP_NETIF_CONNECTED_BIT, 1000)) {
Serial.println("Failed to connect to internet!");
} else {
Serial.println("Connected to internet!");
}
} else {
Serial.println("Failed to connect to network!");
}
}

void loop() {
if (PPP.connected()) {
testClient("google.com", 80);
}
delay(20000);
}
9 changes: 9 additions & 0 deletions libraries/PPP/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=PPP
version=1.0.0
author=Hristo Gochkov
maintainer=Hristo Gochkov <[email protected]>
sentence=Enables network connection using GSM Modem.
paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through GSM Modem.
category=Communication
url=
architectures=esp32
Loading
Loading