23  Cellular IoT Implementations

In 60 Seconds

Building cellular IoT devices involves selecting a module (SIM7000 for NB-IoT, SIM7070 for LTE-M, BG96 for dual-mode), connecting it via UART to a microcontroller, configuring APN settings with AT commands, and implementing HTTP or MQTT clients for cloud communication. The key difference from smartphone development is designing for constrained bandwidth (payloads under 1KB), intermittent connectivity (10-second wake delays from PSM), and aggressive power management (sleep 99.9% of the time).

Key Concepts
  • AT Commands: Standardized command set for configuring and controlling cellular modems; prefixed with “AT”; examples: AT+CEREG? (registration status), AT+NSOST (NB-IoT UDP send)
  • PPP (Point-to-Point Protocol): Legacy method for establishing IP connectivity through cellular modem via serial port; being replaced by ECM/NCM USB Ethernet emulation
  • ECM/NCM (Ethernet Control Model/Network Control Model): USB device classes emulating Ethernet interface over cellular modem; provides standard Linux network interface (eth0/usb0)
  • MQTT-SN (MQTT for Sensor Networks): MQTT adaptation for constrained networks; uses UDP transport; supports sleeping clients with broker-buffered messages for NB-IoT
  • CoAP (Constrained Application Protocol): UDP-based REST protocol optimized for M2M; confirmable messages provide reliability; used with DTLS for security on NB-IoT/LTE-M
  • LwM2M (Lightweight M2M): OMA standard device management protocol for cellular IoT; runs over CoAP/DTLS; provides firmware update, device management, and resource model
  • Quectel/SIMCom Modules: Popular cellular IoT module manufacturers; modules like Quectel BC660K (NB-IoT), BG96 (LTE-M+NB-IoT+GPS), EC21 (LTE Cat-1) expose AT command interface
  • Modem Firmware Update: Critical maintenance operation updating modem baseband firmware; requires specific tooling (Quectel QFlash, Sierra AT+WDSD), can brick device if interrupted

23.1 Learning Objectives

By the end of this chapter, you will be able to:

  • Justify Module Selection: Evaluate LTE-M, NB-IoT, and 4G module trade-offs and defend a selection for specific IoT application requirements
  • Assemble Hardware Connections: Wire SIM7000/SIM7600 modules to Arduino and ESP32 platforms with correct power supply, UART, and antenna configurations
  • Construct AT Command Sequences: Compose AT command flows for network registration, APN configuration, and data transmission over cellular links
  • Implement HTTP/MQTT Clients: Build cellular-connected applications that publish sensor data to cloud services and subscribe to command topics
  • Optimize Data Plans: Configure APN settings and calculate monthly data costs based on payload size, reporting frequency, and carrier pricing models
  • Diagnose Connectivity Failures: Systematically isolate power, serial, SIM, signal, and network registration faults using AT diagnostic commands

Deep Dives:

Comparisons:

Application Protocols:

Learning:

  • Quizzes Hub - Test your cellular IoT implementation knowledge

23.2 Prerequisites

Before diving into this chapter, you should be familiar with:

  • Cellular IoT Fundamentals: Understanding of NB-IoT, LTE-M technologies, their specifications, and when to use each cellular technology is essential for module selection and configuration
  • IoT Protocols Fundamentals: Knowledge of the IoT protocol stack, UDP vs TCP transport layers, and application protocols helps you understand how cellular modules fit into the overall architecture
  • Networking Basics: Familiarity with IP addressing, DNS, network routing, and basic networking concepts is needed to configure APNs and troubleshoot connectivity issues

Cellular IoT lets your devices connect to the internet anywhere there’s cell coverage—just like your phone. This chapter teaches you how to actually build with cellular modules.

What You Need:

  1. Cellular Module: A small board with a radio (like SIM7000)
  2. SIM Card: Just like in your phone (get an IoT data plan)
  3. Microcontroller: Arduino, ESP32, or Raspberry Pi
  4. Antenna: Usually included with the module
  5. Power Supply: Cellular modules need more power than Wi-Fi

The Basic Connection:

Microcontroller → Serial UART → Cellular Module → Antenna → Cell Tower → Internet

Why Cellular for IoT?

  • Works anywhere with cell coverage (no Wi-Fi needed)
  • Low power modes (NB-IoT, LTE-M)
  • Secure and reliable
  • Pay-per-device data plans (~$2-10/month)

“Today we are actually building something!” Sammy the Sensor said eagerly. “To connect me to a cell tower, you need a cellular module – a little board with a radio and a SIM card slot. You wire it to a microcontroller, type in some AT commands, and suddenly I can send my data to the cloud from anywhere with cell coverage!”

“AT commands are like texting instructions to the module,” Lila the LED explained. “You type ‘AT+CGATT=1’ to attach to the network, ‘AT+CIPSTART’ to open a connection, and ‘AT+CIPSEND’ to send data. It sounds complicated, but it is really just a conversation between the microcontroller and the cellular radio – ask a question, get an answer!”

Max the Microcontroller grinned. “I handle all the tricky parts – like configuring the APN (that is the gateway name your carrier uses), managing the serial connection to the module, and handling retries when the signal is weak. The key difference from phone development is that we send tiny packets – maybe 50 to 100 bytes – and then go right back to sleep.”

“Power management is everything,” Bella the Battery emphasized. “Cellular radios are hungry – they can draw 200 milliamps during transmission! But the secret is that we only transmit for a few seconds, then sleep for minutes or hours. With PSM enabled, the device sleeps at just 5 microamps. That is the difference between lasting two weeks and lasting ten years!”

23.3 Understanding Check: Asset Tracking with NB-IoT

⏱️ ~15 min | ⭐⭐⭐ Advanced | 📋 P09.C19.U01

Scenario: You’re tracking 500 shipping containers across North America. Each container reports GPS location + temperature every 30 minutes. You need 10-year battery life on 2× D-cell batteries (19,000 mAh @ 3.6V). Containers travel through rural areas with spotty coverage. Budget: $50K for 500 devices (hardware + 5-year connectivity).

Think about:

  1. Should you use NB-IoT or LTE-M modules? Why?
  2. How do you achieve 10-year battery life when cellular transmission consumes 200mA for 2 seconds?

Key Insight: Use NB-IoT modules (e.g., SIM7020 at $15 each) with Power Saving Mode (PSM) and extended DRX. NB-IoT’s superior coverage (164 dB MCL vs 156 dB for LTE-M) ensures connectivity in rural areas and inside metal containers. LTE-M would offer mobility handoff but drain battery 3× faster for this stationary use case.

Power calculation: Each transmission cycle (wake → connect → send 100 bytes → PSM) consumes ~400 mWh. At 48 transmissions/day × 365 days × 10 years = 175,200 transmissions. Total energy: 70 Wh. Two D-cells provide 68 Wh (19Ah × 3.6V) × 85% efficiency ≈ 58 Wh—close but achievable with careful firmware optimization and reducing retries.

Cost: 500 modules × $15 = $7,500 + SIM cards ($5 each) = $10,000 hardware. Connectivity: NB-IoT data plan at $2/month × 500 devices × 60 months = $60,000 (exceeds budget—negotiate bulk discount to $1.20/month = $36K total, or use annual prepaid plans).

Verify Your Understanding:

  • Why would LTE-M’s mobility features actually waste battery for stationary containers?
  • How does PSM differ from eDRX for power savings?
Cross-Hub Connections

Hands-On Practice:

  • Simulations Hub - Try the Power Budget Calculator to verify 10-year battery life calculations
  • Videos Hub - Watch cellular module setup tutorials and AT command demonstrations

Self-Assessment:

  • Quizzes Hub - Test your understanding of module selection, AT commands, and power optimization

Knowledge Reinforcement:

  • Knowledge Gaps Hub - Clarify common misconceptions about cellular IoT power consumption and connectivity costs
Common Misconception: “Cellular IoT is Just Like a Phone”

Myth: You can use cellular IoT modules just like a smartphone—always connected, instant data transfer.

Reality: IoT modules optimize for battery life, not speed. Key differences:

  1. Power Consumption: Smartphone: ~500mA continuous (2-hour battery). IoT module with PSM: 5µA sleep + 200mA for 2sec bursts (10-year battery).

  2. Connection Time: Smartphone: Always connected (0ms). NB-IoT: 5-10 seconds to establish connection from PSM sleep. LTE-M with eDRX: 1-2 seconds.

  3. Data Rate: Smartphone 4G: 100 Mbps download. NB-IoT: 26 kbps download (3,846× slower!). LTE-M: 1 Mbps (100× slower).

  4. Cost Model: Smartphone: Unlimited data ($50/month). IoT SIM: Pay-per-MB ($0.10/MB) or fixed 10MB/month ($2).

Quantified Impact: A developer assumed NB-IoT had “4G speeds” and designed a video streaming application. Reality check: Streaming 1MB video at 26 kbps takes 5 minutes (vs 0.08 seconds on 4G). After 1 week, 500 devices × 1GB/day × $0.10/MB = $50,000/week connectivity bill (expected $1,400/week). Cost overrun: 3,571%.

Best Practice: Design for constrained bandwidth (send JSON payloads <1KB), intermittent connectivity (tolerate 10-second delays), and aggressive power management (sleep 99.9% of the time). This is the opposite of smartphone app development.

The monthly data cost for cellular IoT depends on payload size and reporting frequency:

\[\text{Monthly Cost} = N \times f_{daily} \times 30 \times P_{bytes} \times C_{per\_MB}\]

where \(N\) is device count, \(f_{daily}\) is reports per day, \(P_{bytes}\) is payload size, and \(C_{per\_MB}\) is cost per megabyte.

Example: 500 sensors reporting temperature every 15 minutes: - Reports per day: \(f_{daily} = \frac{24 \times 60}{15} = 96\) - Payload options: - Bloated JSON: 250 bytes (formatted with whitespace) - Compact JSON: 60 bytes (minified) - Binary format: 12 bytes (packed struct)

Monthly costs at $0.10/MB:

  • Bloated: \(500 \times 96 \times 30 \times 250 / 1,000,000 \times 0.10 = \$36,000\)
  • Compact: \(500 \times 96 \times 30 \times 60 / 1,000,000 \times 0.10 = \$8,640\)
  • Binary: \(500 \times 96 \times 30 \times 12 / 1,000,000 \times 0.10 = \$1,728\)

Switching from bloated JSON to binary saves $34,272/month (95% reduction). For 10,000 devices, the difference is $685,000/month. Payload optimization is critical at IoT scale.

Try It: Cellular IoT Data Cost Calculator

Estimate your monthly connectivity costs based on device count, reporting frequency, and payload size — matching the cost formula from the section above.

23.4 Module Selection and Hardware Setup

23.4.2 Hardware Connection: SIM7000 + ESP32

Complete Wiring Diagram:

Wiring diagram showing ESP32 connected to SIM7000 cellular module via hardware UART (GPIO17 TX to SIM7000 RX, GPIO16 RX to SIM7000 TX), with LiPo battery powering both devices, 1000 microfarad capacitor near VBAT for current spikes, PWR_KEY on GPIO4 for module power control, and external LTE antenna connected to SIM7000
Figure 23.2: SIM7000 to ESP32 wiring diagram with LiPo battery power

Critical Hardware Notes:

  1. Power Supply: SIM7000 draws 2A peak during transmission. Use LiPo battery (not USB power—causes brownouts). Add 1000µF capacitor near VBAT for current spikes.

  2. UART Serial: Connect ESP32 GPIO17 (TX) → SIM7000 RX, GPIO16 (RX) → SIM7000 TX. Baud rate: 115200. Use hardware serial, not software serial (timing critical).

  3. PWR_KEY: Hold GPIO4 LOW for 1 second to power on module. LED blinks slowly (1s) when connected to network, rapidly (200ms) when searching.

  4. Antenna: MUST connect external antenna before powering on. Running without antenna damages RF amplifier.

  5. SIM Card: Insert before powering on. Check PIN code is disabled (or use AT+CPIN=1234 to unlock).

23.5 AT Command Fundamentals

23.5.1 AT Command Flow

Cellular modules communicate via AT commands (Hayes command set). Basic pattern:

Host → AT+COMMAND=value\r\n
Module → response\r\n
Module → OK\r\n  (or ERROR)

Complete Connection Sequence:

Sequence diagram showing AT command flow between host MCU and cellular module: AT test, AT+CPIN SIM check, AT+CGDCONT APN configuration, AT+CREG network registration with 30-60 second wait, AT+CGACT PDP context activation, AT+HTTPINIT and AT+HTTPACTION for HTTP data transmission, followed by AT+CPSMS for power saving mode entry
Figure 23.3: AT command sequence for cellular IoT network registration and data transmission

23.5.2 Essential AT Commands

Basic Module Control:

AT              // Test connection (returns OK)
ATI             // Module information
AT+CGMR         // Firmware version
AT+CFUN=1       // Full functionality mode
AT+CFUN=0       // Minimum functionality (radio off)

SIM and Network:

AT+CPIN?        // Check SIM status (READY/SIM PIN/ERROR)
AT+CPIN=1234    // Unlock SIM with PIN code
AT+COPS?        // Check registered network operator
AT+COPS=?       // Scan available networks (slow: 20-60s)
AT+COPS=0       // Auto-select network (best signal)
AT+CSQ          // Signal quality (0-31 RSSI, 99=unknown)
                // Good: >15 (-93 dBm), Excellent: >25 (-73 dBm)
AT+CREG?        // Network registration status
                // 0,1 = registered home network
                // 0,5 = registered roaming
AT+CGATT?       // GPRS attach status (1=attached)

Data Connection (APN Configuration):

// Configure APN (Access Point Name) - carrier-specific
AT+CGDCONT=1,"IP","iot.1nce.net"           // 1NCE IoT SIM
AT+CGDCONT=1,"IP","hologram"               // Hologram global SIM
AT+CGDCONT=1,"IP","m2m.com.attz"           // AT&T IoT SIM
AT+CGDCONT=1,"IP","iot.truphone.com"       // Truphone IoT
AT+CGDCONT=1,"IP","soracom.io"             // Soracom global IoT

// Activate PDP context (get IP address)
AT+CGACT=1,1    // Activate context ID 1
AT+CGPADDR=1    // Query assigned IP address
AT+CGDATA="PPP",1  // Enter data mode (PPP connection)

HTTP Client (Quick Cloud Integration):

AT+HTTPINIT                                     // Initialize HTTP
AT+HTTPPARA="CID",1                             // Set PDP context ID
AT+HTTPPARA="URL","http://api.thingspeak.com/update"
AT+HTTPPARA="CONTENT","application/json"        // Set content type
AT+HTTPDATA=50,5000                             // Prepare 50 bytes, 5s timeout
// After DOWNLOAD prompt, send payload:
{"api_key":"ABC123","field1":23.5}
AT+HTTPACTION=1                                 // Execute POST (0=GET, 1=POST, 2=HEAD)
AT+HTTPREAD                                     // Read response
AT+HTTPTERM                                     // Terminate HTTP

MQTT Client (Persistent Connections):

// Configure MQTT broker
AT+SMCONF="URL","mqtt.example.com","1883"       // Broker address and port
AT+SMCONF="CLIENTID","device001"                // Client ID
AT+SMCONF="USERNAME","user"                     // Username (if required)
AT+SMCONF="PASSWORD","pass"                     // Password
AT+SMCONF="KEEPTIME",60                         // Keep-alive interval (seconds)

// Connect to broker
AT+SMCONN                                       // Connect (returns OK or ERROR)
AT+SMSTATE?                                     // Check connection state (1=connected)

// Publish message
AT+SMPUB="sensors/temp",20,1,0                  // Topic, length, QoS, retain
// After > prompt, send payload:
{"temperature":23.5}

// Subscribe to topic
AT+SMSUB="commands/led",1                       // Topic, QoS
// Received messages trigger URC: +SMSUB: "commands/led"

// Disconnect
AT+SMDISC                                       // Disconnect from broker

Power Saving Modes:

// Power Saving Mode (PSM) - deepest sleep
AT+CPSMS=1,"","","00000100","00000001"          // Enable PSM
// T3324 (active timer): 4 seconds, T3412 (periodic TAU): 1 hour
// Module sleeps for ~1 hour between wake-ups

// Extended DRX (eDRX) - periodic paging
AT+CEDRXS=1,5,"0101"                            // Enable eDRX for LTE-M
// Paging interval: 20.48 seconds (balance power vs latency)

// Light sleep (clock gating)
AT+CSCLK=2                                      // Auto sleep when UART idle
// Module enters 1mA sleep between commands (wakes on UART RX)

// Airplane mode (radio off, 0.1mA)
AT+CFUN=4                                       // Airplane mode
AT+CFUN=1                                       // Return to full functionality
Try It: PSM Timer Decoder

Decode the T3324 (Active Timer) and T3412 (Periodic TAU) values used in AT+CPSMS commands. These 8-bit binary strings control how long the module stays reachable after communication and how often it wakes for Tracking Area Updates.

Objective: Cellular modules use AT commands to send HTTP requests. This Wokwi lab demonstrates the same HTTP client pattern using ESP32 Wi-Fi, so you can understand the cloud communication flow before working with actual cellular hardware.

Code to Try:

#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "Wokwi-GUEST";
const char* password = "";

void setup() {
  Serial.begin(115200);
  // Step 1: Connect (equivalent to AT+CGATT=1)
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) { delay(500); }
  Serial.printf("Attached! RSSI: %d dBm\n", WiFi.RSSI());
}

void loop() {
  float temp = 22.0 + random(-50, 50) / 10.0;
  // Step 2: HTTP POST (equivalent to AT+HTTPACTION=1)
  HTTPClient http;
  http.begin("http://httpbin.org/post");
  http.addHeader("Content-Type", "application/json");
  String payload = "{\"temp\":" + String(temp, 1) +
                   ",\"device\":\"ESP32-001\"}";
  int httpCode = http.POST(payload);
  if (httpCode > 0)
    Serial.printf("HTTP %d | %d bytes sent\n", httpCode, payload.length());
  http.end();
  // Step 3: Sleep (cellular: would use PSM for hours)
  delay(15000);
}

What to Observe:

  1. The connection flow mirrors cellular AT commands: attach to network, check signal, send data, sleep
  2. Each HTTP POST shows payload size and round-trip time – on real NB-IoT this would be 2-10 seconds instead of milliseconds
  3. The JSON payload is under 100 bytes – critical for cellular IoT where data costs $0.10/MB
  4. In production, you would replace delay(15000) with ESP32 deep sleep + RTC wakeup for years of battery life

23.6 Complete Arduino Implementation

23.6.1 Hardware Serial Cellular Library

Example: ESP32 + SIM7000 Sending Sensor Data

The core pattern connects via AT commands, sends data over HTTP, then enters PSM sleep:

HardwareSerial sim7000(1);  // UART1 on ESP32
#define SIM_TX 17
#define SIM_RX 16
#define SIM_PWR_KEY 4

void setup() {
  sim7000.begin(115200, SERIAL_8N1, SIM_RX, SIM_TX);
  powerOnModule();        // Hold PWR_KEY LOW 1s then HIGH
  initCellular();         // AT -> CPIN? -> CGDCONT -> CREG? -> CGACT
}

void loop() {
  float temp = 23.5 + random(-50, 50) / 10.0;
  sendData(temp, 60.0);  // HTTP GET to ThingSpeak
  enterSleepMode(600);   // PSM + ESP32 deep sleep 10 min
}
#include <HardwareSerial.h>

// SIM7000 on ESP32 hardware serial
HardwareSerial sim7000(1);  // UART1
#define SIM_TX 17
#define SIM_RX 16
#define SIM_PWR_KEY 4

// APN configuration (change for your carrier)
const char* APN = "iot.1nce.net";
const char* SERVER = "api.thingspeak.com";
const char* API_KEY = "YOUR_API_KEY";

void setup() {
  Serial.begin(115200);  // Debug console
  sim7000.begin(115200, SERIAL_8N1, SIM_RX, SIM_TX);  // SIM7000 serial

  // Power on module
  pinMode(SIM_PWR_KEY, OUTPUT);
  powerOnModule();

  // Wait for module ready
  delay(5000);

  // Initialize cellular connection
  if (initCellular()) {
    Serial.println("Cellular connected!");
  } else {
    Serial.println("Connection failed");
  }
}

void loop() {
  // Simulate sensor reading
  float temperature = 23.5 + random(-50, 50) / 10.0;
  float humidity = 60.0 + random(-100, 100) / 10.0;

  // Send data to cloud
  sendData(temperature, humidity);

  // Sleep for 10 minutes
  enterSleepMode(600);  // 600 seconds
}

void powerOnModule() {
  digitalWrite(SIM_PWR_KEY, LOW);
  delay(1000);  // Hold for 1 second
  digitalWrite(SIM_PWR_KEY, HIGH);
  delay(2000);
  Serial.println("Module powered on");
}

bool sendATCommand(String cmd, String expected, int timeout) {
  sim7000.println(cmd);
  long start = millis();
  String response = "";

  while (millis() - start < timeout) {
    while (sim7000.available()) {
      char c = sim7000.read();
      response += c;
      Serial.write(c);  // Echo to console
    }
    if (response.indexOf(expected) != -1) {
      return true;
    }
  }
  return false;
}

bool initCellular() {
  Serial.println("Initializing cellular...");

  // Test module
  if (!sendATCommand("AT", "OK", 2000)) {
    Serial.println("Module not responding");
    return false;
  }

  // Check SIM card
  if (!sendATCommand("AT+CPIN?", "READY", 5000)) {
    Serial.println("SIM card error");
    return false;
  }

  // Configure APN
  String apnCmd = "AT+CGDCONT=1,\"IP\",\"" + String(APN) + "\"";
  if (!sendATCommand(apnCmd, "OK", 2000)) {
    Serial.println("APN config failed");
    return false;
  }

  // Wait for network registration (can take 30-60 seconds)
  Serial.println("Waiting for network... (30-60s)");
  int retries = 30;
  while (retries-- > 0) {
    if (sendATCommand("AT+CREG?", "+CREG: 0,1", 2000) ||
        sendATCommand("AT+CREG?", "+CREG: 0,5", 2000)) {
      Serial.println("Registered on network!");
      break;
    }
    delay(2000);
  }

  if (retries <= 0) {
    Serial.println("Network registration timeout");
    return false;
  }

  // Activate PDP context
  if (!sendATCommand("AT+CGACT=1,1", "OK", 30000)) {
    Serial.println("PDP activation failed");
    return false;
  }

  // Check signal quality
  sim7000.println("AT+CSQ");
  delay(500);
  while (sim7000.available()) {
    Serial.write(sim7000.read());
  }

  return true;
}

bool sendData(float temp, float humidity) {
  Serial.println("Sending data via HTTP...");

  // Initialize HTTP
  if (!sendATCommand("AT+HTTPINIT", "OK", 2000)) {
    return false;
  }

  // Set CID
  if (!sendATCommand("AT+HTTPPARA=\"CID\",1", "OK", 2000)) {
    sendATCommand("AT+HTTPTERM", "OK", 2000);
    return false;
  }

  // Build URL with GET parameters
  String url = "http://" + String(SERVER) + "/update?api_key=" +
               String(API_KEY) + "&field1=" + String(temp) +
               "&field2=" + String(humidity);

  String urlCmd = "AT+HTTPPARA=\"URL\",\"" + url + "\"";
  if (!sendATCommand(urlCmd, "OK", 2000)) {
    sendATCommand("AT+HTTPTERM", "OK", 2000);
    return false;
  }

  // Execute GET request
  if (!sendATCommand("AT+HTTPACTION=0", "+HTTPACTION: 0,200", 10000)) {
    Serial.println("HTTP request failed");
    sendATCommand("AT+HTTPTERM", "OK", 2000);
    return false;
  }

  Serial.println("Data sent successfully!");

  // Terminate HTTP
  sendATCommand("AT+HTTPTERM", "OK", 2000);

  return true;
}

void enterSleepMode(int seconds) {
  Serial.println("Entering power saving mode...");

  // Enable PSM (customize T3324 and T3412 timers as needed)
  sendATCommand("AT+CPSMS=1", "OK", 2000);

  // Light sleep (module wakes on timer or UART activity)
  sendATCommand("AT+CSCLK=2", "OK", 2000);

  // Put ESP32 to deep sleep
  Serial.flush();
  esp_sleep_enable_timer_wakeup(seconds * 1000000ULL);  // microseconds
  esp_deep_sleep_start();
}

Key Implementation Notes:

  1. Hardware Serial: Use HardwareSerial, not SoftwareSerial. SIM7000 requires precise timing (115200 baud) that software serial can’t guarantee.

  2. Power-On Sequence: Hold PWR_KEY LOW for 1 second, then HIGH. LED should start blinking. Wait 5 seconds for RDY message.

  3. Network Registration Time: Can take 30-60 seconds in weak signal areas. NB-IoT takes longer than LTE-M due to cell search process.

  4. HTTP vs MQTT: Use HTTP for simple publish (stateless, no persistent connection). Use MQTT for bidirectional, low-latency communication (persistent connection).

  5. Power Saving: Combining ESP32 deep sleep (10µA) + SIM7000 PSM (5µA) achieves ~15µA total system sleep current.

23.7 Complete IoT Pipeline Architecture

End-to-End System:

End-to-end cellular IoT pipeline showing ESP32 reading DHT22 sensor, waking SIM7000 from PSM, network attach to eNodeB, MQTT publish of JSON payload through HiveMQ broker to InfluxDB time-series database, with Grafana dashboard for visualization and the complete cycle taking approximately 10 seconds active time
Figure 23.4: End-to-end cellular IoT architecture from sensor to cloud dashboard

Data Flow Timeline:

  1. Device Wake-Up (10ms): ESP32 wakes from deep sleep, reads DHT22 sensor via I2C
  2. Module Power-On (1s): ESP32 toggles PWR_KEY to wake SIM7000 from PSM
  3. Network Attach (5-10s): SIM7000 sends TAU (Tracking Area Update) to eNodeB, receives IP address
  4. MQTT Connect (2-5s): TCP handshake + TLS handshake + MQTT CONNECT packet
  5. Publish Data (500ms): MQTT PUBLISH with 50-byte JSON payload {"temp":23.5,"hum":60}
  6. MQTT Broker (100ms): HiveMQ receives, distributes to subscribers, stores in InfluxDB
  7. Dashboard Update (200ms): Grafana queries InfluxDB, updates chart in web browser
  8. Return to Sleep (2s): MQTT DISCONNECT, SIM7000 enters PSM, ESP32 enters deep sleep

Total Active Time: ~10 seconds (0.003% duty cycle for 1-hour reporting interval)

23.8 Troubleshooting Guide

Common Issues and Solutions:

Troubleshooting flowchart for cellular IoT modules: check power supply first (LiPo not USB), then verify serial UART communication at 115200 baud, check SIM card status with AT+CPIN, test signal quality with AT+CSQ, verify network registration with AT+CREG, and finally test data connection with AT+CGACT and AT+HTTPACTION
Figure 23.5: Cellular IoT troubleshooting flowchart for common connection issues

Diagnostic Commands:

// Module health check
AT+CGMR           // Firmware version (should return version string)
AT+CCID           // SIM card ICCID (20-digit number)
AT+CIMI           // SIM card IMSI (15-digit number)

// Signal diagnostics
AT+CSQ            // Signal quality (15-31 = good, <10 = poor)
AT+CPSI?          // Detailed signal info (RSRP, RSRQ, SNR)
                  // Example: +CPSI: LTE NB-IOT,Online,
                  //          RSRP -95 dBm, RSRQ -10 dB, SNR 5 dB

// Network diagnostics
AT+COPS?          // Current operator (e.g., "AT&T", "Verizon")
AT+CREG=2         // Enable network registration URCs
AT+CREG?          // Registration status + location (LAC, CID)
AT+CGPADDR=1      // Assigned IP address (e.g., 10.45.23.12)

// Data usage tracking
AT+CGDCONT?       // Active PDP contexts (shows APN configuration)
AT+CGACT?         // PDP context activation status (1=active, 0=inactive)

// Power diagnostics
AT+CPSMS?         // PSM configuration (timers T3324, T3412)
AT+CEDRXS?        // eDRX configuration (paging interval)
AT+CPMUTEMP       // Module temperature (°C) - should be <60°C
Try It: Signal Quality Interpreter

Enter the CSQ value returned by AT+CSQ to see the corresponding RSSI in dBm and signal quality rating — useful when debugging connectivity in the field.

Common Error Codes:

Error Code Meaning Solution
+CME ERROR: 10 SIM not inserted SIM card not detected Reseat SIM, check orientation (notch corner)
+CME ERROR: 14 SIM busy SIM PIN required or initialization Disable PIN: AT+CLCK="SC",0,"1234"
+CME ERROR: 30 No network service Not registered on network Move outdoors, wait 60s, check signal
+CME ERROR: 32 Network not allowed SIM not activated for roaming Contact carrier, enable roaming
ERROR Unknown command AT command syntax error Check command spelling, add \r\n

23.9 Real-World Deployment Considerations

23.9.1 SIM Card Selection and Activation

IoT SIM Providers:

Provider Coverage Data Plans Features Cost
1NCE 165 countries 500MB/10 years (prepaid) Zero config, auto-roaming $10 one-time
Hologram 196 countries Pay-as-you-go $0.40/MB Global SIM, dashboard API $0.60/month + usage
Soracom 140 countries $0.10/MB Japan, $0.80/MB global Virtual SIM (eSIM), VPN $1.20/month + usage
Twilio 200+ countries $2/month + $0.10/MB Programmable, SMS included $2/month + usage
Truphone 190 countries $2/month + $0.50/MB Multi-IMSI, local breakout $2/month + usage

Activation Checklist:

  1. Purchase SIM: Buy IoT SIM (not consumer phone SIM—different APN and billing)
  2. Register Device: Log into provider portal, register ICCID (SIM card ID) and IMEI (module ID)
  3. Configure APN: Get APN from provider (e.g., iot.1nce.net), configure with AT+CGDCONT
  4. Test Connection: Send test data, verify dashboard shows usage
  5. Monitor Usage: Set up alerts for 80% data quota (avoid overage charges)

23.9.2 Data Plan Optimization

Bandwidth Math:

Sending 100-byte JSON payload every 30 minutes for 1 year:

  • Packets/day: 24 hours × 2 transmissions/hour = 48 packets/day
  • Bytes/day: 48 × 100 bytes = 4.8 KB/day
  • Total/year: 4.8 KB × 365 days = 1.75 MB/year

Plan Comparison:

  • 1NCE (500MB/10 years): $10 one-time = $1/year → Cheapest for low-data
  • Hologram ($0.40/MB): 1.75 MB × $0.40 = $0.70/year + $0.60/month × 12 = $7.90/year
  • Twilio ($2/month + $0.10/MB): $24/year + $0.18 = $24.18/year

Best Practice: For low-data applications (<10MB/month), use prepaid plans (1NCE). For high-data or unpredictable usage, use pay-as-you-go (Hologram).

23.9.3 Antenna Selection and Placement

Antenna Types:

Type Gain Range Placement Use Case
Stubby (50mm) 0-2 dBi Indoor only On module Prototyping, indoor sensors
Whip (150mm) 3-5 dBi Indoor/outdoor Vertical mount General IoT, trackers
Magnetic (200mm) 5-7 dBi Outdoor Vehicle roof Asset tracking, mobile
External Panel 8-12 dBi Long range Outdoor pole Remote installations, rural

Placement Rules:

  1. Vertical Orientation: LTE antennas are vertically polarized. Mount antenna perpendicular to ground for best signal.
  2. Ground Plane: Metal surface improves stubby antenna performance by 3-5 dB (vehicle roof, metal enclosure).
  3. Keep Clear: 10cm clearance from metal objects, batteries, cables (avoid RF detuning).
  4. Cable Length: Use <5m cables (longer cables = 1 dB loss per meter at 2100 MHz).

Signal Strength Impact:

  • Stubby Indoor: -95 dBm (marginal) → 10% packet loss
  • Whip Outdoor: -75 dBm (excellent) → <1% packet loss
  • External Panel Rural: -105 dBm (usable) → 5% packet loss with NB-IoT

23.9.4 Power Budget Analysis

Complete Power Profile (SIM7000 NB-IoT):

State Current Duration Energy per Cycle
Deep Sleep (PSM) 5 µA 3599s 0.018 mAh
Wake-Up 50 mA 1s 0.014 mAh
Network Attach 150 mA 5s 0.208 mAh
TX Peak 220 mA 2s 0.122 mAh
RX Listen 50 mA 1s 0.014 mAh
Return to Sleep 10 mA 2s 0.006 mAh
Total per Hour 3600s 0.382 mAh/hour

Battery Life Calculation:

Battery capacity: 2000 mAh (2× AA NiMH) Hourly consumption: 0.382 mAh Battery life: 2000 mAh ÷ 0.382 mAh/hour = 5,236 hours = 218 days = 7.2 months

Extending to 10 Years:

Need: 10 years × 365 days × 24 hours × 0.382 mAh = 33,487 mAh Solution: Use 2× D-cell LiSOCl₂ batteries (19,000 mAh each = 38,000 mAh total)

Verification: 38,000 mAh ÷ (0.382 mAh × 24) = 10.3 years

Power Optimization Tips:

  1. Increase Reporting Interval: 30 min → 1 hour = 2× battery life
  2. Reduce TX Power: -10 dBm instead of +23 dBm = 1.5× battery life (if signal allows)
  3. Use NB-IoT over LTE-M: NB-IoT = 5µA PSM vs LTE-M = 1mA eDRX = 200× better sleep current
  4. Optimize Payload: 100 bytes → 50 bytes = 1.5× battery life (less TX time)
Try It: Power Budget Calculator

Configure your cellular IoT power profile to estimate battery life. Adjust sleep current, transmission parameters, and battery capacity to match the power budget table from the chapter.

23.11 Summary

  • Module Selection Strategy guides your choice between NB-IoT and LTE-M based on mobility, data rate, and battery requirements. Use NB-IoT (SIM7020) for stationary sensors requiring 10-year battery life, and LTE-M (SIM7070) for mobile tracking with voice support.

  • Hardware Configuration requires careful attention to power supply (LiPo battery, not USB), antenna connection before power-on, and hardware serial for reliable AT command communication at 115200 baud.

  • AT Command Mastery enables network registration, APN configuration, and data transmission. The complete sequence from power-on to data upload typically takes 10-20 seconds, with network registration being the longest step (30-60 seconds in weak signal areas).

  • Power Optimization combines ESP32 deep sleep (10 microamps) with SIM7000 PSM (5 microamps) to achieve 15 microamps total system current, enabling 10-year battery life with 38,000 mAh D-cell batteries.

  • Data Plan Economics favor prepaid plans like 1NCE ($10 for 500MB/10 years) for low-data applications, while pay-as-you-go providers suit variable usage patterns. A 100-byte payload every 30 minutes consumes only 1.75 MB/year.

  • Troubleshooting Diagnostics rely on key AT commands: AT+CSQ for signal quality (aim for >15), AT+CPIN? for SIM status, AT+CREG? for network registration, and AT+CGACT? for PDP context activation.

  • Common Pitfall Avoidance requires designing for constrained bandwidth (under 1 KB payloads) and intermittent connectivity, not smartphone-style always-on connections. Misunderstanding this causes cost overruns exceeding 3,500%.

23.12 Knowledge Check

23.13 Concept Relationships

How This Connects

Builds on:

Implements:

Extends to:

23.14 See Also

Related Resources

Module Datasheets:

Development Boards:

AT Command References:

Code Libraries:

23.15 Try It Yourself

Hands-On Challenge

Task: Build and test a cellular IoT sensor that reports to the cloud.

Hardware Needed:

  • ESP32 development board
  • SIM7000 cellular module (or BG96)
  • IoT SIM card (1NCE, Hologram, or carrier SIM)
  • LiPo battery (3.7V, 2000+ mAh)
  • DHT22 temperature/humidity sensor
  • External LTE antenna

Challenge Steps:

1. Hardware Assembly

  • Wire SIM7000 to ESP32 hardware serial (TX→16, RX→17)
  • Connect LiPo battery to SIM7000 VBAT (add 1000µF capacitor)
  • Attach external antenna to SIM7000 antenna connector
  • Wire DHT22 sensor to ESP32 GPIO pin

2. Basic Connectivity Test Write Arduino code to: - Power on module with PWR_KEY - Check SIM card status (AT+CPIN?) - Register on network (AT+CREG?) - Get signal quality (AT+CSQ) and log RSSI - Activate PDP context (AT+CGACT=1,1) - Get IP address (AT+CGPADDR=1)

3. Sensor Data Transmission Extend code to: - Read DHT22 temperature and humidity every 5 minutes - Format data as JSON: {"temp":23.5,"humidity":60.2,"device":"ESP32-001"} - Send via HTTP POST to ThingSpeak or your cloud endpoint - Enter PSM sleep mode between transmissions

4. Power Optimization Measure and optimize: - Baseline current during transmission: _____ mA - PSM sleep current: _____ µA - Calculated battery life with 2000 mAh battery: _____ days - Target: Achieve >30 days on single charge

5. Troubleshooting Exercise Deliberately introduce these faults and diagnose: - Remove antenna → Should see AT+CSQ return low RSSI - Wrong APN → AT+CGACT=1,1 fails - Insufficient power → Module resets during transmission - Use your diagnostic script to identify each fault

Expected Learning Outcomes:

  • Understand AT command flow from power-on to data transmission
  • Experience real network registration delays (30-60s)
  • Learn to interpret signal quality and coverage issues
  • Calculate actual power consumption vs theoretical
  • Build troubleshooting intuition for field deployments

Bonus Challenge:

  • Implement MQTT instead of HTTP for persistent connection
  • Add geofencing alerts using GPS coordinates
  • Create a dashboard to visualize sensor data over time
  • Optimize payload size to minimize data costs (<100 bytes/message)

Common Pitfalls

Sending AT commands to cellular modems without hardware flow control (RTS/CTS) or software flow control (XON/XOFF) causes buffer overflows on high-speed UART at rates >115200 baud. Buffer overflow results in corrupted AT responses, missed URCs (Unsolicited Result Codes), and modem unresponsiveness. Always configure UART hardware flow control and implement a command queue with response timeout of at least 300 ms for standard AT commands.

Cellular modems require 5–60 seconds to complete network registration after power-up, depending on signal strength, coverage class, and PLMN selection. Firmware that sends data immediately after modem initialization without checking AT+CEREG registration status will fail silently. Poll AT+CEREG every 2 seconds with a 90-second timeout; fall back to restarting the modem if registration fails within the timeout period.

TCP’s three-way handshake, ACK overhead, and keep-alive traffic consume significant data on metered cellular plans. A TCP connection with 10-second keep-alive generates 1,440 packets/day of pure overhead — using ~7 MB/month on a device with a 10 MB data plan. Use UDP + application-layer acknowledgment (CoAP confirmable, MQTT-SN with QoS 1) for short sensor messages; reserve TCP for high-reliability command channels where session continuity is needed.

APN settings vary by carrier, country, and M2M vs consumer plan. Hardcoding a specific APN (e.g., “m2m.verizon.com”) means the device fails on a different carrier or when the user changes carriers via eSIM. Store APN settings in non-volatile configuration, allow runtime modification via device management protocol (LwM2M object /11/0/1), and provide a fallback discovery mechanism (try known APNs in order if user-configured APN fails).

23.16 What’s Next

Chapter Focus Link
Cellular IoT Comprehensive Review NB-IoT vs LTE-M comparison, network architecture review cellular-iot-comprehensive-review.html
NB-IoT Labs and Implementation Hands-on NB-IoT module configuration and testing nb-iot-labs-and-implementation.html
Cellular IoT Power Optimization PSM/eDRX timer configuration, signaling optimization cellular-iot-power-optimization.html
Cellular IoT Deployment Planning Coverage analysis, carrier selection, field deployment cellular-iot-deployment-planning.html
Cellular IoT Applications Real-world use cases: smart metering, fleet tracking, agriculture cellular-iot-applications.html

In the next chapter, Cellular IoT Comprehensive Review, we compare NB-IoT vs LTE-M in depth, explore network architecture, and review quiz questions to solidify your understanding.