Skip to content

Commit 4960d86

Browse files
Add support for PPP Modems to Arduino (espressif#9518)
* feat(ppp): Add support for PPP Modems * feat(sdk): Add libs with PPP enabled * ci(pre-commit): Apply automatic fixes * IDF c432c692fa (espressif#9527) --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 6b3a9a9 commit 4960d86

14 files changed

+1176
-74
lines changed

CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ set(ARDUINO_ALL_LIBRARIES
9595
LittleFS
9696
NetBIOS
9797
Network
98+
PPP
9899
Preferences
99100
RainMaker
100101
SD_MMC
@@ -157,6 +158,10 @@ set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp)
157158

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

161+
set(ARDUINO_LIBRARY_PPP_SRCS
162+
libraries/PPP/src/PPP.cpp
163+
libraries/PPP/src/ppp.c)
164+
160165
set(ARDUINO_LIBRARY_Preferences_SRCS libraries/Preferences/src/Preferences.cpp)
161166

162167
set(ARDUINO_LIBRARY_RainMaker_SRCS

Kconfig.projbuild

+10
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,16 @@ config ARDUINO_SELECTIVE_Networking
321321
depends on ARDUINO_SELECTIVE_COMPILATION
322322
default y
323323

324+
config ARDUINO_SELECTIVE_Ethernet
325+
bool "Enable Ethernet"
326+
depends on ARDUINO_SELECTIVE_COMPILATION
327+
default y
328+
329+
config ARDUINO_SELECTIVE_PPP
330+
bool "Enable PPP"
331+
depends on ARDUINO_SELECTIVE_COMPILATION
332+
default y
333+
324334
config ARDUINO_SELECTIVE_ArduinoOTA
325335
bool "Enable ArduinoOTA"
326336
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking

cores/esp32/esp32-hal-periman.c

+6
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ const char* perimanGetTypeName(peripheral_bus_type_t type) {
104104
case ESP32_BUS_TYPE_ETHERNET_MCD: return "ETHERNET_MCD";
105105
case ESP32_BUS_TYPE_ETHERNET_MDIO: return "ETHERNET_MDIO";
106106
case ESP32_BUS_TYPE_ETHERNET_PWR: return "ETHERNET_PWR";
107+
#endif
108+
#if CONFIG_LWIP_PPP_SUPPORT
109+
case ESP32_BUS_TYPE_PPP_TX: return "PPP_MODEM_TX";
110+
case ESP32_BUS_TYPE_PPP_RX: return "PPP_MODEM_RX";
111+
case ESP32_BUS_TYPE_PPP_RTS: return "PPP_MODEM_RTS";
112+
case ESP32_BUS_TYPE_PPP_CTS: return "PPP_MODEM_CTS";
107113
#endif
108114
default: return "UNKNOWN";
109115
}

cores/esp32/esp32-hal-periman.h

+6
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ extern "C" {
102102
ESP32_BUS_TYPE_ETHERNET_MCD, // IO is used as ETHERNET MCD pin
103103
ESP32_BUS_TYPE_ETHERNET_MDIO, // IO is used as ETHERNET MDIO pin
104104
ESP32_BUS_TYPE_ETHERNET_PWR, // IO is used as ETHERNET PWR pin
105+
#endif
106+
#if CONFIG_LWIP_PPP_SUPPORT
107+
ESP32_BUS_TYPE_PPP_TX, // IO is used as PPP Modem TX pin
108+
ESP32_BUS_TYPE_PPP_RX, // IO is used as PPP Modem RX pin
109+
ESP32_BUS_TYPE_PPP_RTS, // IO is used as PPP Modem RTS pin
110+
ESP32_BUS_TYPE_PPP_CTS, // IO is used as PPP Modem CTS pin
105111
#endif
106112
ESP32_BUS_TYPE_MAX
107113
} peripheral_bus_type_t;

idf_component.yml

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ dependencies:
4545
idf: ">=5.1"
4646
# mdns 1.2.1 is necessary to build H2 with no WiFi
4747
mdns: "^1.2.3"
48+
espressif/esp_modem: "^1.1.0"
4849
chmorgan/esp-libhelix-mp3:
4950
version: "1.0.3"
5051
require: public

libraries/Network/src/NetworkEvents.cpp

+8-10
Original file line numberDiff line numberDiff line change
@@ -319,16 +319,14 @@ const char *NetworkEvents::eventName(arduino_event_id_t id) {
319319
case ARDUINO_EVENT_ETH_DISCONNECTED: return "ETH_DISCONNECTED";
320320
case ARDUINO_EVENT_ETH_GOT_IP: return "ETH_GOT_IP";
321321
case ARDUINO_EVENT_ETH_LOST_IP: return "ETH_LOST_IP";
322-
case ARDUINO_EVENT_ETH_GOT_IP6:
323-
return "ETH_GOT_IP6";
324-
325-
// case ARDUINO_EVENT_PPP_START: return "PPP_START";
326-
// case ARDUINO_EVENT_PPP_STOP: return "PPP_STOP";
327-
// case ARDUINO_EVENT_PPP_CONNECTED: return "PPP_CONNECTED";
328-
// case ARDUINO_EVENT_PPP_DISCONNECTED: return "PPP_DISCONNECTED";
329-
// case ARDUINO_EVENT_PPP_GOT_IP: return "PPP_GOT_IP";
330-
// case ARDUINO_EVENT_PPP_LOST_IP: return "PPP_LOST_IP";
331-
// case ARDUINO_EVENT_PPP_GOT_IP6: return "PPP_GOT_IP6";
322+
case ARDUINO_EVENT_ETH_GOT_IP6: return "ETH_GOT_IP6";
323+
case ARDUINO_EVENT_PPP_START: return "PPP_START";
324+
case ARDUINO_EVENT_PPP_STOP: return "PPP_STOP";
325+
case ARDUINO_EVENT_PPP_CONNECTED: return "PPP_CONNECTED";
326+
case ARDUINO_EVENT_PPP_DISCONNECTED: return "PPP_DISCONNECTED";
327+
case ARDUINO_EVENT_PPP_GOT_IP: return "PPP_GOT_IP";
328+
case ARDUINO_EVENT_PPP_LOST_IP: return "PPP_LOST_IP";
329+
case ARDUINO_EVENT_PPP_GOT_IP6: return "PPP_GOT_IP6";
332330
#if SOC_WIFI_SUPPORTED
333331
case ARDUINO_EVENT_WIFI_OFF: return "WIFI_OFF";
334332
case ARDUINO_EVENT_WIFI_READY: return "WIFI_READY";

libraries/Network/src/NetworkEvents.h

+8-7
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@ typedef enum {
7878
ARDUINO_EVENT_PROV_CRED_FAIL,
7979
ARDUINO_EVENT_PROV_CRED_SUCCESS,
8080
#endif
81-
// ARDUINO_EVENT_PPP_START,
82-
// ARDUINO_EVENT_PPP_STOP,
83-
// ARDUINO_EVENT_PPP_CONNECTED,
84-
// ARDUINO_EVENT_PPP_DISCONNECTED,
85-
// ARDUINO_EVENT_PPP_GOT_IP,
86-
// ARDUINO_EVENT_PPP_LOST_IP,
87-
// ARDUINO_EVENT_PPP_GOT_IP6,
81+
ARDUINO_EVENT_PPP_START,
82+
ARDUINO_EVENT_PPP_STOP,
83+
ARDUINO_EVENT_PPP_CONNECTED,
84+
ARDUINO_EVENT_PPP_DISCONNECTED,
85+
ARDUINO_EVENT_PPP_GOT_IP,
86+
ARDUINO_EVENT_PPP_LOST_IP,
87+
ARDUINO_EVENT_PPP_GOT_IP6,
8888
ARDUINO_EVENT_MAX
8989
} arduino_event_id_t;
9090

@@ -146,6 +146,7 @@ class NetworkEvents {
146146

147147
friend class ESP_NetworkInterface;
148148
friend class ETHClass;
149+
friend class PPPClass;
149150
#if SOC_WIFI_SUPPORTED
150151
friend class STAClass;
151152
friend class APClass;

libraries/Network/src/NetworkInterface.cpp

+19-23
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,11 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data) {
7171
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP;
7272
} else
7373
#endif
74-
// if(_interface_id == ESP_NETIF_ID_PPP){
75-
// arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP;
76-
// } else
77-
if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
78-
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP;
79-
}
74+
if (_interface_id == ESP_NETIF_ID_PPP) {
75+
arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP;
76+
} else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
77+
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP;
78+
}
8079
} else if (event_id == _lost_ip_event_id) {
8180
clearStatusBits(ESP_NETIF_HAS_IP_BIT);
8281
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
@@ -87,12 +86,11 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data) {
8786
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_LOST_IP;
8887
} else
8988
#endif
90-
// if(_interface_id == ESP_NETIF_ID_PPP){
91-
// arduino_event.event_id = ARDUINO_EVENT_PPP_LOST_IP;
92-
// } else
93-
if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
94-
arduino_event.event_id = ARDUINO_EVENT_ETH_LOST_IP;
95-
}
89+
if (_interface_id == ESP_NETIF_ID_PPP) {
90+
arduino_event.event_id = ARDUINO_EVENT_PPP_LOST_IP;
91+
} else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
92+
arduino_event.event_id = ARDUINO_EVENT_ETH_LOST_IP;
93+
}
9694
} else if (event_id == IP_EVENT_GOT_IP6) {
9795
ip_event_got_ip6_t* event = (ip_event_got_ip6_t*)event_data;
9896
esp_ip6_addr_type_t addr_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
@@ -117,12 +115,11 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data) {
117115
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_GOT_IP6;
118116
} else
119117
#endif
120-
// if(_interface_id == ESP_NETIF_ID_PPP){
121-
// arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP6;
122-
// } else
123-
if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
124-
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP6;
125-
}
118+
if (_interface_id == ESP_NETIF_ID_PPP) {
119+
arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP6;
120+
} else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) {
121+
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP6;
122+
}
126123
#if SOC_WIFI_SUPPORTED
127124
} else if (event_id == IP_EVENT_AP_STAIPASSIGNED && _interface_id == ESP_NETIF_ID_AP) {
128125
setStatusBits(ESP_NETIF_HAS_IP_BIT);
@@ -536,7 +533,7 @@ String NetworkInterface::impl_name(void) const {
536533
char netif_name[8];
537534
esp_err_t err = esp_netif_get_netif_impl_name(_esp_netif, netif_name);
538535
if (err != ESP_OK) {
539-
log_e("Failed to get netif impl_name: %d", err);
536+
log_e("Failed to get netif impl_name: 0x%04x %s", err, esp_err_to_name(err));
540537
return String("");
541538
}
542539
return String(netif_name);
@@ -562,7 +559,7 @@ bool NetworkInterface::setDefault() {
562559
}
563560
esp_err_t err = esp_netif_set_default_netif(_esp_netif);
564561
if (err != ESP_OK) {
565-
log_e("Failed to set default netif: %d", err);
562+
log_e("Failed to set default netif: 0x%04x %s", err, esp_err_to_name(err));
566563
return false;
567564
}
568565
return true;
@@ -576,15 +573,14 @@ bool NetworkInterface::isDefault() const {
576573
}
577574

578575
uint8_t* NetworkInterface::macAddress(uint8_t* mac) const {
579-
if (!mac || _esp_netif == NULL) {
576+
if (!mac || _esp_netif == NULL || _interface_id == ESP_NETIF_ID_PPP) {
580577
return NULL;
581578
}
582579
esp_err_t err = esp_netif_get_mac(_esp_netif, mac);
583580
if (err != ESP_OK) {
584-
log_e("Failed to get netif mac: %d", err);
581+
log_e("Failed to get netif mac: 0x%04x %s", err, esp_err_to_name(err));
585582
return NULL;
586583
}
587-
// getMac(mac);
588584
return mac;
589585
}
590586

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#include <PPP.h>
2+
3+
#define PPP_MODEM_APN "internet"
4+
#define PPP_MODEM_PIN "0000" // or NULL
5+
6+
// WaveShare SIM7600 HW Flow Control
7+
#define PPP_MODEM_RST 25
8+
#define PPP_MODEM_RST_LOW false //active HIGH
9+
#define PPP_MODEM_TX 21
10+
#define PPP_MODEM_RX 22
11+
#define PPP_MODEM_RTS 26
12+
#define PPP_MODEM_CTS 27
13+
#define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_HW
14+
#define PPP_MODEM_MODEL PPP_MODEM_SIM7600
15+
16+
// SIM800 basic module with just TX,RX and RST
17+
// #define PPP_MODEM_RST 0
18+
// #define PPP_MODEM_RST_LOW true //active LOW
19+
// #define PPP_MODEM_TX 2
20+
// #define PPP_MODEM_RX 19
21+
// #define PPP_MODEM_RTS -1
22+
// #define PPP_MODEM_CTS -1
23+
// #define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_NONE
24+
// #define PPP_MODEM_MODEL PPP_MODEM_SIM800
25+
26+
void onEvent(arduino_event_id_t event, arduino_event_info_t info) {
27+
switch (event) {
28+
case ARDUINO_EVENT_PPP_START:
29+
Serial.println("PPP Started");
30+
break;
31+
case ARDUINO_EVENT_PPP_CONNECTED:
32+
Serial.println("PPP Connected");
33+
break;
34+
case ARDUINO_EVENT_PPP_GOT_IP:
35+
Serial.println("PPP Got IP");
36+
break;
37+
case ARDUINO_EVENT_PPP_LOST_IP:
38+
Serial.println("PPP Lost IP");
39+
break;
40+
case ARDUINO_EVENT_PPP_DISCONNECTED:
41+
Serial.println("PPP Disconnected");
42+
break;
43+
case ARDUINO_EVENT_PPP_STOP:
44+
Serial.println("PPP Stopped");
45+
break;
46+
default:
47+
break;
48+
}
49+
}
50+
51+
void testClient(const char* host, uint16_t port) {
52+
NetworkClient client;
53+
if (!client.connect(host, port)) {
54+
Serial.println("Connection Failed");
55+
return;
56+
}
57+
client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
58+
while (client.connected() && !client.available())
59+
;
60+
while (client.available()) {
61+
client.read(); //Serial.write(client.read());
62+
}
63+
64+
Serial.println("Connection Success");
65+
client.stop();
66+
}
67+
68+
void setup() {
69+
Serial.begin(115200);
70+
71+
// Listen for modem events
72+
Network.onEvent(onEvent);
73+
74+
// Configure the modem
75+
PPP.setApn(PPP_MODEM_APN);
76+
PPP.setPin(PPP_MODEM_PIN);
77+
PPP.setResetPin(PPP_MODEM_RST, PPP_MODEM_RST_LOW);
78+
PPP.setPins(PPP_MODEM_TX, PPP_MODEM_RX, PPP_MODEM_RTS, PPP_MODEM_CTS, PPP_MODEM_FC);
79+
80+
Serial.println("Starting the modem. It might take a while!");
81+
PPP.begin(PPP_MODEM_MODEL);
82+
83+
Serial.print("Manufacturer: ");
84+
Serial.println(PPP.cmd("AT+CGMI", 10000));
85+
Serial.print("Model: ");
86+
Serial.println(PPP.moduleName());
87+
Serial.print("IMEI: ");
88+
Serial.println(PPP.IMEI());
89+
90+
bool attached = PPP.attached();
91+
if (!attached) {
92+
int i = 0;
93+
unsigned int s = millis();
94+
Serial.print("Waiting to connect to network");
95+
while (!attached && ((++i) < 600)) {
96+
Serial.print(".");
97+
delay(100);
98+
attached = PPP.attached();
99+
}
100+
Serial.print((millis() - s) / 1000.0, 1);
101+
Serial.println("s");
102+
attached = PPP.attached();
103+
}
104+
105+
Serial.print("Attached: ");
106+
Serial.println(attached);
107+
Serial.print("State: ");
108+
Serial.println(PPP.radioState());
109+
if (attached) {
110+
Serial.print("Operator: ");
111+
Serial.println(PPP.operatorName());
112+
Serial.print("IMSI: ");
113+
Serial.println(PPP.IMSI());
114+
Serial.print("RSSI: ");
115+
Serial.println(PPP.RSSI());
116+
int ber = PPP.BER();
117+
if (ber > 0) {
118+
Serial.print("BER: ");
119+
Serial.println(ber);
120+
Serial.print("NetMode: ");
121+
Serial.println(PPP.networkMode());
122+
}
123+
124+
Serial.println("Switching to data mode...");
125+
PPP.mode(ESP_MODEM_MODE_CMUX); // Data and Command mixed mode
126+
if (!PPP.waitStatusBits(ESP_NETIF_CONNECTED_BIT, 1000)) {
127+
Serial.println("Failed to connect to internet!");
128+
} else {
129+
Serial.println("Connected to internet!");
130+
}
131+
} else {
132+
Serial.println("Failed to connect to network!");
133+
}
134+
}
135+
136+
void loop() {
137+
if (PPP.connected()) {
138+
testClient("google.com", 80);
139+
}
140+
delay(20000);
141+
}

libraries/PPP/library.properties

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=PPP
2+
version=1.0.0
3+
author=Hristo Gochkov
4+
maintainer=Hristo Gochkov <hristo@espressif.com>
5+
sentence=Enables network connection using GSM Modem.
6+
paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through GSM Modem.
7+
category=Communication
8+
url=
9+
architectures=esp32

0 commit comments

Comments
 (0)