To use 4G on an ESP32 PLC you need the 4G (M1)-NB1 IoT LTE communication board (u-blox SARA-R412M), a SIM with an LTE-M or NB-IoT data plan and an antenna. In the Arduino IDE, select your ESP32 PLC model and set Tools > Extension module 1 to LTE for LTE-M or NB for NB-IoT. The NB library of the Industrial Shields boards package registers the modem on the network, and its NBClient works with ArduinoHttpClient for HTTP and with PubSubClient for MQTT.
This guide shows how to insert the SIM card, which menu options to choose, and two sketches: an HTTP request and an MQTT client that publishes and subscribes. The syntax of both has been checked, but they have not been compiled or tested on a PLC, so compile and test them on your own ESP32 PLC before you use them. At the end there is a table to find the cause when the PLC does not connect.
- Step 1Board and SIM4G board in slot 1, LTE-M or NB-IoT SIM, antenna
- Step 2Arduino IDEModel, version v3 and Extension module
- Step 3Attachbegin() with PIN and APN, then attachGPRS()
- Step 4Send dataHTTP or MQTT over NBClient
Why use 4G on an ESP32 PLC
The ESP32 PLC already has Wi-Fi, Bluetooth and Ethernet. They need a local network. A 4G board lets the PLC send data from places without one: pumping stations, wells, vehicles, railway carriages or machines at a customer site where you cannot use the plant network. LTE-M and NB-IoT are the 4G technologies made for this kind of device: low data volume, low power and good coverage.
A mobile link loses coverage from time to time. Plan for it from the start: keep the data on the PLC while the link is down and send it when it comes back.
Hardware you need
- An ESP32 PLC with the 4G (M1)-NB1 IoT LTE (u-blox) communication board. On the product page, choose it as communication board 1. The board carries a u-blox SARA-R412M module.
- A SIM card with a data plan for LTE-M (LTE Cat M1) or NB-IoT. Ask your operator which one it supports in your area and which APN to use.
- An LTE antenna connected to the 4G board.
- A computer with the Arduino IDE and the Industrial Shields boards package. See How to install Industrial Shields boards in the Arduino IDE.
Which 4G board? The NB library in the boards package works with the u-blox SARA-R412M and SARA-R422M8S modules: it reads the model of the modem and stops with an error if it is a different one. This guide is for the 4G (M1)-NB1 IoT LTE (u-blox) board. If your PLC has a Quectel or an LTE Cat 4 board, ask our technical team which library to use. The ESP32 PLC 14 can be ordered with 4G integrated: see Sending messages via SMS or Telegram with an ESP32 PLC 14.
Insert the SIM card in the ESP32 PLC
Disconnect the power before you open the cover.
- Remove the cover of the Ethernet port. Put a finger in the Ethernet port and push up to lift the cover, or lift it gently from one side with a flat screwdriver.
- Insert the SIM card. The SIM slot is above the reset button. Insert the card with the contacts facing up.
- Put the cover back. Press it down until it clicks into place.


Configure the Arduino IDE for the 4G board
The 4G board is optional, so you tell the IDE where it is. These options are in the Tools menu:
| Menu | Value | Note |
|---|---|---|
| Board | Industrial Shields ESP32 Boards > ESP32 PLC Family | Installed with the boards package |
| Model | Your model, for example ESP32 PLC 21 IO+ | It sets the I/O map of the PLC |
| Version | v3 | The NB and LTE options exist only for v3. v1 is the legacy version |
| Extension module 1 | LTE for LTE-M, or NB for NB-IoT | Use Extension module 2 if the board is in slot 2 |
The option you choose in Extension module decides the radio technology. With LTE, the library sets the modem to LTE Cat M1 (AT+URAT=7). With NB, it sets NB-IoT (AT+URAT=8). If the SIM only works on LTE-M and you choose NB, the PLC never registers. The GPRS option is for the 2G GPRS board, not for the 4G board.
If no module is selected, the sketch does not compile and shows: No NB expansion module has been defined. Please select one in Tools -> Extension module.
The NB library comes with the boards package. Its examples are in File > Examples > NB: NBWebClient, NBSSLWebClient, SendSMS, ReceiveSMS and, under Tools, TestModem, TestGPRS and NBScanNetworks. For the sketches below, also install two libraries from Sketch > Include Library > Manage Libraries:
- ArduinoHttpClient, for HTTP.
- PubSubClient, for MQTT.
Example 1: send an HTTP request over 4G
The sketch registers on the mobile network, opens the data connection and sends a GET request to httpbin.org, a public test service that answers with the request it receives. Fill in the PIN and the APN of your SIM. Leave the PIN empty if the SIM has no PIN.
#include <NB.h>
#include <ArduinoHttpClient.h>
// Uncomment once if the modem does not answer: it finds the baud rate and sets it to 38400
// #define MAKE_AUTOBAUD
const char PINNUMBER[] = ""; // SIM PIN, empty if the SIM has no PIN
const char APN[] = ""; // APN of your operator
const char USERNAME[] = ""; // only if the operator asks for it
const char PASSWORD[] = "";
NBClient nbClient;
GPRS gprs;
NB nbAccess; // NB nbAccess(true); prints every AT command on the serial monitor
const char server[] = "httpbin.org";
const int port = 80;
HttpClient http(nbClient, server, port);
void setup() {
Serial.begin(115200);
Serial.println("Starting the 4G web client");
#ifdef MAKE_AUTOBAUD
if (!nbAccess.autobaud()) {
Serial.println("Autobaud failed, check the Extension module setting");
while (true);
}
nbAccess.shutdown();
#endif
// Register on the LTE-M or NB-IoT network and open the data connection
while (nbAccess.begin(PINNUMBER, APN, USERNAME, PASSWORD) != NB_READY ||
gprs.attachGPRS() != GPRS_READY) {
Serial.println("Not connected, retrying");
delay(1000);
}
Serial.println("Connected to the mobile network");
int err = http.get("/get");
if (err != 0) {
Serial.print("Request failed, error ");
Serial.println(err);
return;
}
int status = http.responseStatusCode();
String body = http.responseBody();
Serial.print("HTTP status: ");
Serial.println(status);
Serial.println(body);
http.stop();
}
void loop() {
}
How it works:
nbAccess.begin(PIN, APN, USERNAME, PASSWORD)starts the modem, applies the settings and waits until it is registered on the network. It returnsNB_READY.gprs.attachGPRS()opens the data connection and returnsGPRS_READY. The name comes from the Arduino MKR NB library this one is based on: the connection uses LTE-M or NB-IoT, not 2G.NBClientis a standard ArduinoClient, soHttpClientuses it like an Ethernet or Wi-Fi client.http.get()returns 0 when the request is sent.responseStatusCode()gives the HTTP status (200 if all is well) andresponseBody()the answer.
Open the serial monitor at 115200 baud. Registration takes at least 24 seconds, because the library resets the modem and restarts its radio, and can take a few minutes the first time, while the modem searches for the network.
Example 2: publish and subscribe with MQTT over 4G
MQTT sends small messages through a broker. It needs little data, so it suits LTE-M and NB-IoT. This sketch connects to a public test broker, publishes a message, subscribes to the same topic and prints every message it receives.
#include <NB.h>
#include <PubSubClient.h>
const char PINNUMBER[] = ""; // SIM PIN, empty if the SIM has no PIN
const char APN[] = ""; // APN of your operator
const char USERNAME[] = "";
const char PASSWORD[] = "";
NBClient nbClient;
GPRS gprs;
NB nbAccess;
PubSubClient mqtt(nbClient);
const char* MQTT_SERVER = "broker.hivemq.com"; // public test broker: no login, no TLS
const int MQTT_PORT = 1883;
const char* TOPIC = "test/esp32plc-4g";
const char* CLIENT_ID = "esp32plc-4g-0001"; // must be unique on the broker
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message on ");
Serial.print(topic);
Serial.print(": ");
for (unsigned int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
void connectNetwork() {
while (nbAccess.begin(PINNUMBER, APN, USERNAME, PASSWORD) != NB_READY ||
gprs.attachGPRS() != GPRS_READY) {
Serial.println("Not connected, retrying");
delay(1000);
}
Serial.println("Connected to the mobile network");
}
void connectMqtt() {
Serial.print("Connecting to the MQTT broker... ");
if (mqtt.connect(CLIENT_ID)) {
Serial.println("connected");
mqtt.publish(TOPIC, "Hello from the ESP32 PLC over 4G");
mqtt.subscribe(TOPIC);
} else {
Serial.print("failed, state ");
Serial.println(mqtt.state());
delay(5000);
}
}
void setup() {
Serial.begin(115200);
connectNetwork();
mqtt.setServer(MQTT_SERVER, MQTT_PORT);
mqtt.setCallback(callback);
}
void loop() {
if (!mqtt.connected()) {
if (!nbAccess.isAccessAlive()) {
connectNetwork(); // registration lost: attach again
}
connectMqtt();
}
mqtt.loop();
}
How it works:
connectNetwork()registers on the network and opens the data connection, as in example 1.connectMqtt()makes one connection attempt. If it fails, it prints the error code and waits 5 seconds.- In
loop(), if MQTT is disconnected,isAccessAlive()checks the registration withAT+CEREG?. If the PLC has lost the network, it attaches again before it reconnects to the broker. mqtt.loop()keeps the connection alive and callscallback()for each message that arrives.
The client ID must be unique on the broker: if two devices use the same one, the broker disconnects the first. broker.hivemq.com is a public test broker without login or encryption, so anyone can read the topic. For a real installation, use your own broker with a user, a password and TLS. See MQTT over TLS with the ESP32 PLC and MQTT security fundamentals.
The delay(5000) and the retry loops block the program. That is fine for a test. In a PLC that also controls outputs, reconnect without blocking, as in non-blocking reconnection on an ESP32 PLC.
LTE-M or NB-IoT: which one to choose
| LTE-M (LTE Cat M1) | NB-IoT | |
|---|---|---|
| Extension module option | LTE | NB |
| Data rate | Hundreds of kbit/s | Tens of kbit/s |
| Devices that move | Yes, it changes cell while connected | Better for fixed devices |
| Fits | MQTT and HTTP with frequent messages, firmware downloads, vehicles | Small messages a few times per hour, fixed sites, deep indoor coverage |
Both depend on the operator: check that your SIM and your area have the one you choose. The library also sets the Standard Europe operator profile of the modem and LTE bands 3, 8 and 20, which are the usual bands for LTE-M and NB-IoT in Europe. If your operator uses other bands, ask our technical team before you install.
Troubleshooting the 4G connection
| What you see | Likely cause | What to do |
|---|---|---|
| Compile error: No NB expansion module has been defined | Extension module is set to None | Set Tools > Extension module 1 (or 2) to LTE or NB |
| The modem does not answer, begin() returns an error at once | The modem uses a different baud rate | Uncomment #define MAKE_AUTOBAUD and upload once. The library tries several baud rates and leaves the modem at 38400. Comment it again afterwards |
| "Not connected, retrying" without end | Wrong technology (NB or LTE), wrong APN or PIN, no antenna, no coverage, or the SIM has no LTE-M or NB-IoT | Check the menu option, the APN and the antenna. Run the NBScanNetworks and TestGPRS examples |
| You need to see what the modem says | Create the object as NB nbAccess(true);: every AT command and answer goes to the serial monitor | |
| MQTT state -2 | The TCP connection to the broker failed | Check the server name, the port and the data connection |
| MQTT state -4 or -3 | Time-out or connection lost, often weak coverage | Check the antenna and the signal, and keep the data on the PLC until it reconnects |
| MQTT state 2, 4 or 5 | The broker rejects the client ID, the user and password, or the access | Use a unique client ID and the credentials of the broker |
From a test sketch to remote telemetry
A field installation adds three things to these examples: a buffer for the data while there is no coverage, timestamps, and a server that receives the messages from many PLCs. The railway case below sends energy data over 4G LTE-M and keeps it on board when the train has no coverage. The oil well case shows the same pattern from a remote site, with an ESP32 PLC 21 FLEX and a 4G board. To collect the messages from many PLCs, see the Node-RED MQTT concentrator for ESP32 PLC fleets.
Take it further
A 4G link drops and comes back. See how a real project handles coverage, a simulator where you cut the link and the code that keeps the data.
Case study
Comfort on board. Energy data that waits for coverage.
An ESP32 PLC 57R controls light, ventilation and A/C in a railway carriage and sends energy data over 4G LTE-M, with a local buffer.
Read the case study
Simulator
Know your network has failed before the town runs dry
ESP32 PLC RTUs report a town water network over 4G and LoRaWAN. Cut a link and see store and forward, alarms and night flow leak detection.
Open the simulator
PLC Solution Library
Offline-first MQTT data logging with SD buffering
Every message is written to a daily file on the SD card before it is published, so nothing is missing when the network returns.
See the example
FAQ about 4G on the ESP32 PLC
Which SIM card do I need for the ESP32 PLC 4G board?
A SIM with a data plan for LTE-M or NB-IoT, from an operator that offers it in your area. Many IoT SIMs include both. A SIM for 2G only does not work with this board, because the library sets the modem to LTE-M or NB-IoT.
Why does the code use a class called GPRS on a 4G board?
The NB library is based on the Arduino MKR NB library, which keeps the name GPRS for the data connection. attachGPRS() opens the data connection over LTE-M or NB-IoT.
Can I use HTTPS or MQTT with TLS over 4G?
Yes. The NB library includes NBSSLClient, with the NBSSLWebClient example. For MQTT with TLS on the ESP32 PLC, see this guide.
Can the 4G board send SMS?
Yes. The library includes the SendSMS and ReceiveSMS examples, in File > Examples > NB.
What happens to the data when the PLC loses coverage?
The examples above do not keep it. In a real project, write each message to the SD card or to memory first and send it when the link returns. See offline-first MQTT data logging with SD buffering.
More about mobile connectivity and MQTT
- Sending messages via SMS or Telegram using an ESP32 PLC 14 with integrated 4G
- LTE Cat.4 with Raspberry PLC
- Building an MQTT over TLS connection for the ESP32 PLC
- Choosing an industrial controller
Library references: ArduinoHttpClient and PubSubClient API.