|
4G Cat.1 Module in Practice: EC200U Internet Connection Tutorial, Remote Data Collection Made Easy

4G Cat.1 Module in Practice: EC200U Internet Connection Tutorial, Remote Data Collection Made Easy

Why Choose Cat.1?

Friends doing IoT projects have all encountered this problem: devices deployed in the field, WiFi can’t reach, LoRa distance isn’t enough, and 2G is being phased out. What to do?

4G Cat.1 was born for this scenario.

Simply put, Cat.1 is the “simplified version” of 4G:

  • Downlink speed 10Mbps - more than enough for sensor data
  • Low power consumption - standby current only 3mA
  • Wide coverage - directly uses existing 4G base stations
  • Low cost - modules only 25-35 yuan
  • Low latency - much faster response than NB-IoT

Today we’ll use the Quectel EC200U module to build a remote temperature collector, sending data directly to an MQTT server.

What Do You Need?

ItemModel/SpecPrice
4G Cat.1 ModuleQuectel EC200U¥28
Antenna4G rod antenna (SMA connector)¥8
SIM CardIoT card/phone card (data plan required)¥10/month
Development BoardArduino Uno or ESP32¥15
USB to TTLCH340 or CP2102¥5
Jumper WiresMale-to-female, several¥3
Temperature SensorDHT22 (optional)¥8
Total¥77

Module purchase keywords: “EC200U development board” or “EC200U Arduino”, recommend buying one with a breakout board, easier to wire.

Step 1: Hardware Connection

EC200U uses UART communication, wiring is very simple:

EC200U          Arduino/ESP32
─────────────────────────────
VCC      →      5V (Arduino) or 3.3V (ESP32)
GND      →      GND
TX       →      RX (Pin 10)
RX       →      TX (Pin 11)
NET      →      LED (network status indicator, optional)

Notes: ⚠️

  • EC200U can draw up to 500mA during transmission, USB power may not be enough, recommend external 5V/2A power supply
  • TX/RX must be cross-connected (module TX to board RX)
  • Antenna must be connected before powering on, otherwise may damage RF circuit

Step 2: AT Command Testing

Don’t write code yet, test if the module is working with a serial terminal first.

Open Arduino IDE serial monitor, or use PuTTY/SecureCRT directly, set baud rate to 115200, 8N1.

# Send the following commands (add carriage return + newline after each line)

AT
# Should return: OK (if no response, check if TX/RX are reversed)

AT+CPIN?
# Returns SIM card status: +CPIN: READY (if returns NOT INSERTED, check if SIM is inserted properly)

AT+CSQ
# Returns signal quality: +CSQ: 20,99 (20 means good signal, above 10 is okay, 99 means unknown error rate)

AT+COPS?
# Returns carrier: +COPS: 0,0,"CHINA MOBILE"

AT+CGATT?
# Returns attachment status: +CGATT: 1 (attached)

AT+QIACT?
# Returns IP status: +QIACT: 1 (activated)

If AT+CSQ returns less than 10, signal is too poor, change location or add high-gain antenna.

Step 3: Configure APN and Network Connection

Different carriers have different APN settings:

CarrierAPN
China Mobilecmnet
China Unicom3gnet
China Telecomctnet

Method 1: PPP Dial-up (Suitable for Linux Embedded Devices)

# Set APN
AT+CGDCONT=1,"IP","3gnet"

# Dial
ATD*99#
# Returns CONNECT on success, module establishes PPP connection

# Hang up (note 1 second silence before and after)
+++

# Or force hang up
ATH

On Linux you can use pppd to manage dial-up connections, embedded devices can directly use the module’s PPP network interface.

Method 2: TCP Direct Connection Test

IoT projects generally use TCP/UDP for direct communication, which is more convenient:

# Set APN (if not set before)
AT+CGDCONT=1,"IP","3gnet"

# Activate context
AT+CGACT=1,1
# Wait for OK response

# Establish TCP connection (test with public MQTT server)
AT+QIOPEN=1,0,"TCP","broker.emqx.io",1883,0,0
# Wait for response: +QIOPEN: 0,0 means success

# Send data (first specify connection ID and length)
AT+QISEND=0,15
# After seeing > prompt, enter data
Hello from Cat.1!
# Send success response: SEND OK

# Close connection
AT+QICLOSE=0

Step 4: Arduino Driver Code

Below is a complete EC200U driver library, supporting TCP/MQTT connections:

#include <SoftwareSerial.h>

#define EC200U_RX 10
#define EC200U_TX 11

SoftwareSerial ec200u(EC200U_RX, EC200U_TX);

class EC200U {
public:
  EC200U() {}

  bool init() {
    ec200u.begin(115200);
    delay(1000);

    // Test communication
    sendAT("AT");
    if (!waitForOK()) return false;

    // Disable echo
    sendAT("ATE0");
    waitForOK();

    // Set text mode
    sendAT("AT+CMGF=1");
    waitForOK();

    Serial.println("EC200U initialization successful");
    return true;
  }

  bool waitForNetwork(int timeout = 60) {
    Serial.print("Waiting for network registration");
    for (int i = 0; i < timeout; i++) {
      sendAT("AT+CREG?");
      String resp = readResponse();
      if (resp.indexOf("+CREG: 0,1") >= 0 || resp.indexOf("+CREG: 0,5") >= 0) {
        Serial.println("\nNetwork registration successful");
        return true;
      }
      Serial.print(".");
      delay(1000);
    }
    Serial.println("\nNetwork registration timeout");
    return false;
  }

  bool activateGPRS(const char* apn = "cmnet") {
    // Set APN
    sendAT("AT+QICSGP=1,1,\"" + String(apn) + "\",\"\",\"\"");
    if (!waitForOK()) return false;

    // Activate context
    sendAT("AT+QIACT=1");
    for (int i = 0; i < 10; i++) {
      sendAT("AT+QIACT?");
      String resp = readResponse();
      if (resp.indexOf("+QIACT: 1") >= 0) {
        Serial.println("GPRS activation successful");
        return true;
      }
      delay(1000);
    }
    Serial.println("GPRS activation failed");
    return false;
  }

  bool connectMQTT(const char* server, int port,
                   const char* clientID, const char* user,
                   const char* pass) {
    // Configure MQTT
    String cmd = "AT+QMTCFG=\"keepalive\",0,60";
    sendAT(cmd);
    waitForOK();

    cmd = "AT+QMTCFG=\"will\",0,0,0,\"\",\"\",0,0";
    sendAT(cmd);
    waitForOK();

    cmd = "AT+QMTCFG=\"auth\",0," + String(user) + "," + String(pass);
    sendAT(cmd);
    waitForOK();

    // Connect to server
    cmd = "AT+QMTOPEN=0,\"" + String(server) + "\"," + String(port);
    sendAT(cmd);

    // Wait for connection confirmation
    for (int i = 0; i < 30; i++) {
      String resp = readResponse();
      if (resp.indexOf("+QMTOPEN: 0,0") >= 0) {
        Serial.println("MQTT server connection successful");
        break;
      }
      delay(1000);
    }

    // Login
    cmd = "AT+QMTCONN=0,\"" + String(clientID) + "\"";
    sendAT(cmd);

    for (int i = 0; i < 15; i++) {
      String resp = readResponse();
      if (resp.indexOf("+QMTCONN: 0,0,0") >= 0) {
        Serial.println("MQTT login successful");
        return true;
      }
      delay(1000);
    }
    Serial.println("MQTT login failed");
    return false;
  }

  bool publish(const char* topic, const char* message) {
    String cmd = "AT+QMTPUB=0,0,0,0,\"" + String(topic) + "\"," + String(strlen(message));
    sendAT(cmd);
    delay(100);

    // Send message content
    ec200u.print(message);

    for (int i = 0; i < 20; i++) {
      String resp = readResponse();
      if (resp.indexOf("+QMTPUB: 0,0,0") >= 0) {
        return true;
      }
      delay(100);
    }
    return false;
  }

private:
  void sendAT(String cmd) {
    ec200u.println(cmd);
    delay(100);
  }

  String readResponse() {
    String resp = "";
    while (ec200u.available()) {
      resp += ec200u.readStringUntil('\n');
    }
    return resp;
  }

  bool waitForOK(int timeout = 50) {
    for (int i = 0; i < timeout; i++) {
      String line = readResponse();
      if (line.indexOf("OK") >= 0) return true;
      if (line.indexOf("ERROR") >= 0) return false;
      delay(100);
    }
    return false;
  }
};

EC200U gsm;

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

  Serial.println("=== 4G Cat.1 MQTT Collector ===");

  if (!gsm.init()) {
    Serial.println("Module initialization failed, check wiring");
    while (1);
  }

  if (!gsm.waitForNetwork()) {
    Serial.println("Network registration failed, check SIM card and antenna");
    while (1);
  }

  if (!gsm.activateGPRS("cmnet")) {
    Serial.println("GPRS activation failed, check APN settings");
    while (1);
  }

  // Connect to MQTT (replace with your server)
  if (!gsm.connectMQTT("broker.emqx.io", 1883,
                       "arduino_client_001", "", "")) {
    Serial.println("MQTT connection failed");
    while (1);
  }

  Serial.println("System ready, starting to send data");
}

void loop() {
  // Simulate temperature data
  float temperature = 25.0 + random(100) / 10.0;
  float humidity = 60.0 + random(200) / 10.0;

  // Generate JSON
  String payload = "{\"temp\":" + String(temperature) +
                   ",\"hum\":" + String(humidity) +
                   ",\"ts\":" + String(millis()) + "}";

  // Publish to MQTT
  if (gsm.publish("/sensor/arduino001", payload.c_str())) {
    Serial.println("Data sent successfully: " + payload);
  } else {
    Serial.println("Data send failed");
  }

  // Send once every 30 seconds
  delay(30000);
}

How it works:

  • EC200U uses Quectel’s proprietary AT command set (starting with AT+QMT)
  • MQTT connection is two steps: first TCP connect to server, then send MQTT CONNECT packet
  • Data is sent in JSON format, convenient for cloud parsing

Step 5: Test and Verify

After uploading the code, open the serial monitor, you should see:

=== 4G Cat.1 MQTT Collector ===
EC200U initialization successful
Waiting for network registration.....
Network registration successful
GPRS activation successful
MQTT server connection successful
MQTT login successful
System ready, starting to send data
Data sent successfully: {"temp":28.5,"hum":65.2,"ts":123456}

Use an MQTT client (like MQTTX) to subscribe to the /sensor/arduino001 topic, and you’ll receive data in real-time.

Real-World Data Usage Testing

I ran a continuous 24-hour test:

Send IntervalSingle Data SizeDaily SendsDaily DataMonthly Data
30 seconds50 bytes2880144KB4.3MB
1 minute50 bytes144072KB2.2MB
5 minutes50 bytes28814KB432KB

Conclusion: For sensor data collection, a 10MB monthly plan is completely sufficient. IoT cards are generally 10 yuan/month/100MB, very low cost.

Common Problem Troubleshooting

Problem 1: AT command no response

  • Cause: Baud rate incorrect or wiring error
  • Solution: Confirm baud rate 115200, TX/RX cross-connected, check power supply (USB port sometimes doesn’t provide enough power, add a 5V power supply)

Problem 2: +CPIN: NOT INSERTED or +CME ERROR: 3

  • Cause: SIM card not inserted properly or inserted backwards
  • Solution: Re-insert SIM card (power off first), notch facing outward, clean contacts with eraser. Confirm if it’s standard SIM or Nano SIM (needs adapter)

Problem 3: Poor signal quality (CSQ < 10)

  • Cause: Antenna not connected properly or poor location
  • Solution: Tighten antenna, move device to window or put antenna outside metal enclosure, or switch to high-gain antenna

Problem 4: GPRS activation failed / TCP connection timeout

  • Cause: APN setting error, insufficient balance, or server firewall
  • Solution: Confirm APN matches carrier (Mobile cmnet/Unicom 3gnet/Telecom ctnet), check balance, use AT+QPING="broker.emqx.io" to test connectivity, confirm port 1883 is open

Problem 5: MQTT connection timeout / data send failed

  • Cause: Server address error or connection disconnected
  • Solution: First AT+QICLOSE to close then reconnect, check AT+QISTATE before sending to confirm connection status

Advanced Tips

1. Low Power Mode

If device is battery-powered, you can enable sleep:

// Enter sleep
sendAT("AT+QSCLK=1");

// Wake up (pull DTR pin high)
digitalWrite(DTR_PIN, HIGH);
delay(100);
digitalWrite(DTR_PIN, LOW);

EC200U standby current is about 2mA, sleep can reduce to under 1mA. Combined with ESP32’s Deep Sleep and MOS transistor to control module power, two 18650 batteries can last several months.

2. SMS Alerts

Send SMS notification when device is abnormal:

sendAT("AT+CMGS=\"13800138000\"");
delay(100);
ec200u.print("Temperature exceeded limit! Current 85°C");
delay(100);
ec200u.write(0x1A);  // Ctrl+Z to send

3. TCP Transparent Transmission

If you don’t want to use MQTT, you can use TCP transparent transmission directly:

// Open TCP connection
sendAT("AT+QIOPEN=1,0,\"TCP\",\"192.168.1.100\",8080,0,1");

// Send data
sendAT("AT+QISEND=0,10");
ec200u.print("0123456789");

Summary

4G Cat.1 is the “universal solution” for IoT projects:

  • Wider coverage than WiFi
  • Lower latency than LoRa
  • Faster response than NB-IoT
  • Cheaper than 4G Cat.4

The EC200U module, 30 yuan can get your device online anywhere. Combined with MQTT protocol, data collection and remote control are both easy.

Suitable scenarios:

  • Remote data collection (agriculture, industry)
  • Shared devices (power banks, bikes)
  • Mobile device tracking (logistics, pets)
  • Emergency communication backup

The only thing to note is power supply—the 500mA current during transmission may be too much for USB, just use a 5V/2A power supply.


Related resources: