Tài liệu hướng dẫn chung

Tổng hợp các giải pháp Module SIM 4G thay thế SIM800 và SIM900

Như một số trang chính thống đã đưa tin, Bộ Thông tin – Truyền thông đã trình Thủ tướng Chính phủ xem xét phương án dừng công nghệ di động cũ 2G vào năm 2022. Vì vậy đối với những dự án phát triển từ nay trở về sau, anh em cần tìm cho mình module SIM phù hợp để tránh trường hợp phải thay đổi trong quá trình sản xuất cũng như sản phẩm.

Xưa nay anh em quen sử dụng với các dòng module SIM đến từ SIM COM, như SIM900A, SIM800L,… với ưu điểm giá thành rẻ, phổ thông, cộng đồng lớn, tính ổn định,.. Tuy nhiên SIM900A, SIM800L,… chỉ hỗ trợ mạng 2G và GSM. Sau khi nhà mạng dừng công nghẹ 2G, thì những module này sẽ tương ứng với cục gạch – Tương tự với chiếc Nó Kìa huyền thoại 1202 hay 1280.

Đây là những lý do khiến anh em phải đổi qua dòng module SIM mới.

Bảng thống kê module ra chân V1 ( SIMCOM & Quectel) tương thích phần cứng với nhau

NSX module lõi 4G Cat 1+ SMS, No VOLTE 4G Cat 1+SMS+ VOLTE
SIMCOM
Mã SP: TDM2309

Mã lõi: A7680C
Mã SP: SP000584
(Bản CN)

SIMCOM
 
Mã lõi: A7683E
Mã SP: TDM2413
(Bản quốc tế)
   

Mã lõi: A7682S
Mã SP: TDM2430
(Bản VN)

Bảng thống kê module ra chân TDM-4G-V2 tương thích phần cứng với nhau:

NSX module lõi 4G+ SMS, No VOLTE 4G+SMS+ VOLTE 4G+GPS
SIMCOM
Mã SP: SP000765
Mã lõi: A7680C-XXX
NSX lõi: SIMCOM

Mã SP: SP000767
Mã lõi: A7680C-XXX
NSX lõi: SIMCOM

Mã SP: TDM2308
Mã lõi: A7672S-XXX
NSX lõi: SIMCOM
SIMCOM  

Mã SP: TDM2431
Mã lõi: A7682S-XXX
NSX lõi: SIMCOM
 
SIMCOM  

Mã SP: SP25041673
Mã lõi: A7683E-XXX
NSX lõi: SIMCOM
 
Quectel  
Mã SP: SP001076
Mã lõi: EC800G-CN
NSX lõi: Quectel

NO-VOLTE:
Mã SP: TDM2404
Mã lõi: EG800K
NSX lõi: Quectel

 

VOLTE:
Mã SP: TDM2519
Mã lõi: EC800M-CN
NSX lõi: Quectel

Mobiletek    

Mã SP: TDM2406
Mã lõi: LYNQ L511CN

Các kit phát triển 4G đi kèm:

4G CAT 1, SMS, VOLTE 4G CAT 1, SMS, No VOLTE
3G 4G LTE CAT 4, SMS, VOLTE

3G,4G, GPS


Mã SP: TDM2401
Mã lõi: A7680C/A7683E/A7682S**

MCU: ESP32-WROOM-32E


Mã SP: TDM2402
Mã lõi: A7680C/A7683C**

MCU: ESP32-WROOM-32E


Mã SP: SP001060
Mã lõi: A7600C

Ngưng sản xuất


Mã SP: TDM2421
Mã lõi: EG800K


Mã SP: TDM2422
Mã lõi: A7680C/A7683E/A7682S**

MCU: ESP32-C3FH4

   
Mã SP:TDM2421 (bản có volte)
Mã lõi: EC800M-CN

Các sản phẩm 4G LTE CAT 4


4G+SMS+VOLTE

4G + GPS


Mã SP: TDM2201
Mã lõi: A7600C
NSX lõi: SIMCOM

 


Mã SP: TDM2203
Mã lõi: Sim7600CE-M1S

ngưng sx

Ngoài ra còn có các sản phẩm khác như:
Module MINI PCIE 4G


Mã sản phẩm: SP004859

Mã SP: TDM2403

USB Dongle 4G

4G LTE CAT 1, No VOLTE 4G LTE CAT 1 V2, No VOLTE(VOLTE), fit vỏ usb kèm vỏ usb
LTE CAT 4, VOLTE

Mã SP: TDM2310
Mã lõi: A7680C

 

Mã SP: TDM2424
Mã lõi: A7680C(A7682S)


Mã SP: TDM2302
Mã lõi: A7600C

Dưới đây là bảng tóm tắt các module 4G thay thế cho SIM800L, SIM900A và so sánh các thông số cơ bản

Link Module ra chân Loại hoàn thiện băng tần hỗ trợ Loại 4G GPS VOLTE (gọi 4G) Nguồn cấp Khay sim Giá bán Link mua module lõi
TDM-4G-V2-SC Ra chân giống A7670 4G LTE-CAT1 10Mbps không 5-16V Push-push thấp  
TDM-4G-V2-NV Ra chân giống A7670 4G LTE-CAT1 10Mbps không không 5-16V Push-push thấp  
TDM2309-No-volte Ra chân (thay thế trực tiếp SIM800/SIM800L module) 4G LTE-CAT1 10Mbps không không 3.8-4.2V Push-push thấp nhất A7680C
A7680C-VoLTE Ra chân ( thay thế trực tiếp SIM800/SIM800L module) 4G LTE-CAT1 10Mbps không 3.8-4.2V Push-push thấp A7680C ( ghi chú cho shop có volte)
A7670 Ra chân (ngưng sx, Khuyến nghị đổi sang TDM-4G-V2) 4G LTE-CAT1 10Mbps không 5-16V Push-push thấp A7670
A7672S Ra chân 4G/GPS LTE-CAT1 10Mbps 5-16V Open-lock trung bình A7672S
A7600C Ra chân 2G/3G/4G LTE-CAT4 150Mbps không 5-16V Push-push cao A7600C
SIM7600CE Ra chân 2G/3G/4G+GPS LTE-CAT4 150Mbps 5-16V Push-push cao nhất SIM7600CE
SIM7020E Ra chân NB-IoT NB-IoT không không 2.1-3.6V Push-push thấp SIM7020E
A7680C USB Dongle Cổng ra USB 4G LTE-CAT1 10Mbps không không 5V USB Push-pull thấp A7680C
A7600C USB Dongle Cổng ra USB 2G/3G/4G LTE-CAT4 150Mbps Không 5V USB Open-Lock cao A7600C

AT Command Test cho các dòng Module SIM

  1. Giới thiệu phần mềm AT Command Test

Đây là ứng dụng do Linh Kiện Thủ Đức phát triển, dựa trên nhu cầu test và phát triển nhanh các ứng dụng dựa trên module SIM, IoT

Trong quá trình phát triển ứng dụng dành cho các dòng module SIM, nếu có vấn đề gì các bạn có thể liên hệ trực tiếp tới Linh Kiện Thủ Đức, sẽ được hỗ trợ và update nhiệt tình

Cập nhật:

2. Các tính năng cơ bản

– Hỗ trợ các command cơ bản

– Hỗ trợ SMS

– Hỗ trợ Call

– Hỗ trợ MQTT trên nền TCP

– Hỗ trợ MQTT AT command của SIMCOM

– Hỗ trợ GPS (A7600CE) hoặc LBS (Location based service – A7670C, A7600C1)

3. Các tính năng sẽ phát triển

– HTTP(S)

– Hỗ trợ Kết nối PPP (Point to Point)

Lập trình sử dụng module SIM để gửi tin nhắn và gọi điện

Chuẩn bị

  1. Mạch arduino, esp8266 hoặc esp32,… có hỗ trợ Arduino IDE
  2. Module SIM A7680C, A7670C, A7600C, SIM7600CE
  3. Mạch hạ áp LM2596 hoặc tương đương (Đối với A7680C không tích hợp mạch hạ áp)
  4. Nguồn 6-15V 10W
  5. Jack DC
  6. Dây Bus và dây điện
  7. SIM điện thoại di động có thể gọi và gửi tin nhắn
  8. Phần mềm Arduino IDE

Các module 4G thông dụng xem tại đây: Tổng hợp các loại module 4G 5G NB-IoT thông dụng

Kết nối

image.png

Code mẫu(Đây là code mẫu giao tiếp với ESP32 bạn có thể điều chỉnh để phù hợp với Arduino):

#include <HardwareSerial.h>

#define simSerial               Serial2 //Sửa cho phù hợp với module đang dùng
#define MCU_SIM_BAUDRATE        115200
#define MCU_SIM_TX_PIN              17 //Sửa cho phù hợp với module đang dùng
#define MCU_SIM_RX_PIN              16 //Sửa cho phù hợp với module đang dùng
#define MCU_SIM_EN_PIN              15 //Sửa cho phù hợp với module đang dùng

// Thay bằng thông tin WiFi của bạn
const char* ssid = "...";        // Tên mạng WiFi
const char* password = "..."; // Mật khẩu WiFi
// Please update number before test
#define PHONE_NUMBER                "+8498*****" // Nhập SĐT của bạn

void sim_at_wait()
{
    delay(100);
    while (simSerial.available()) {
        Serial.write(simSerial.read());
    }
}

bool sim_at_cmd(String cmd){
    simSerial.println(cmd);
    sim_at_wait();
    return true;
}

bool sim_at_send(char c){
    simSerial.write(c);
    return true;
}

void sent_sms()
{
    sim_at_cmd("AT+CMGF=1");
    String temp = "AT+CMGS=\"";
    temp += (String)PHONE_NUMBER;
    temp += "\"";
    sim_at_cmd(temp);
    sim_at_cmd("ESP32-SIM7600X From linhkienthuduc.com");

    // End charactor for SMS
    sim_at_send(0x1A);
}

void call()
{
    String temp = "ATD";
    temp += PHONE_NUMBER;
    temp += ";";
    sim_at_cmd(temp); 

    delay(20000);

    // Hang up
    sim_at_cmd("ATH"); 
}

void setup() 
{
    /*  Power enable  */
    pinMode(MCU_SIM_EN_PIN,OUTPUT); 
    digitalWrite(MCU_SIM_EN_PIN,LOW); //Sửa cho phù hợp với module đang dùng

    delay(20);
    Serial.begin(115200);
    Serial.println("\n\n\n\n-----------------------\nSystem started!!!!");

    // Delay for power on
    delay(12000);
  

    // Đặt ESP32 ở chế độ Station (kết nối với WiFi)
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    Serial.print("Connecting to ");
    Serial.println(ssid);

    // Chờ kết nối WiFi
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    // Khi kết nối thành công
    Serial.println("");
    Serial.println("WiFi connected!");
    Serial.print("IP Address: ");
    Serial.println(WiFi.localIP());      // Hiển thị địa chỉ IP
    Serial.print("RSSI: ");
    Serial.println(WiFi.RSSI());         // Hiển thị cường độ tín hiệu (dBm)
    Serial.print("MAC Address: ");
    Serial.println(WiFi.macAddress());   // Hiển thị địa chỉ MAC
  
    simSerial.begin(MCU_SIM_BAUDRATE, SERIAL_8N1, MCU_SIM_RX_PIN, MCU_SIM_TX_PIN);
    // Check AT Command
    Serial.println("Checking AT command...");
    sim_at_cmd("AT");

    // Product infor
    sim_at_cmd("ATI");

    // Check SIM Slot
    sim_at_cmd("AT+CPIN?");

    // Check Signal Quality
    sim_at_cmd("AT+CSQ");

    sim_at_cmd("AT+CIMI");

   if (WiFi.status() == WL_CONNECTED) {
        Serial.println("Still connected to WiFi");
        Serial.print("RSSI: ");
        Serial.println(WiFi.RSSI());
    } else {
        Serial.println("WiFi disconnected! Attempting to reconnect...");
        WiFi.reconnect();
    }

    sent_sms();

    // Delay 5s
    delay(5000);   

    call();
}

void loop() 
{     
    if (Serial.available()){
        char c = Serial.read();
        simSerial.write(c);
    }
  sim_at_wait();
  call();
  delay(10000);

  // Chuyển tiếp dữ liệu từ module SIM tới máy tính
  if (simSerial.available()) {
    char c = simSerial.read();
    Serial.write(c);  // Gửi dữ liệu từ module SIM về PC
  }
}

Code mẫu SMS-CALL cảnh báo lửa và khí gas

Code mẫu ở đây dùng sản phẩm Kit phát triển 4G ESP32 LTE CAT 1 WIFI BLE TDM2401 Volte

Bạn có thể nối mạch như sau:

image.png

Lập trình:

Phần cảnh báo có thể dùng chung cho các sản phẩm khác, bạn cần điều chỉnh chân UART cho hợp lệ.

Bạn có thể tham khảo video hướng dẫn cụ thể tại đây: https://www.youtube.com/watch?v=JW7ia1GnZh8


#include <HardwareSerial.h>

#define simSerial               Serial2
#define MCU_SIM_BAUDRATE        115200
#define MCU_SIM_TX_PIN          17
#define MCU_SIM_RX_PIN          16
#define MCU_SIM_EN_PIN          15

// Định nghĩa chân pin cảm biến lửa và MQ2
#define FLAME_PIN               18
#define MQ2_PIN                 32

// Ngưỡng giá trị cho cảm biến MQ2 và cảm biến lửa
#define MQ2_THRESHOLD           800
#define FLAME_THRESHOLD         LOW // Giả sử khi chân pin cảm biến lửa xuất hiện mức LOW là phát hiện lửa

#define PHONE_NUMBER            "0..." //Điền số điện thoại của bạn

void sim_at_wait()
{
    delay(100);
    while (simSerial.available()) {
        Serial.write(simSerial.read());
    }
}

bool sim_at_cmd(String cmd) {
    simSerial.println(cmd);
    sim_at_wait();
    return true;
}


bool sim_at_send(char c){
    simSerial.write(c);
    return true;
}

void sent_sms(String message) {
    sim_at_cmd("AT+CMGF=1"); // Chế độ văn bản
    String temp = "AT+CMGS=\"";
    temp += PHONE_NUMBER;
    temp += "\"";
    sim_at_cmd(temp);
    sim_at_cmd(message); // Nội dung tin nhắn

    // Kết thúc tin nhắn
    sim_at_send(0x1A);
}



void call() {
    String temp = "ATD";
    temp += PHONE_NUMBER;
    temp += ";";
    sim_at_cmd(temp); // Gọi đi

    delay(20000); // Đợi 20 giây

    sim_at_cmd("ATH"); // Cúp máy
}



void setup() 
{
    /*  Bật nguồn mô-đun SIM  */
    pinMode(MCU_SIM_EN_PIN, OUTPUT); 
    digitalWrite(MCU_SIM_EN_PIN, LOW);

    delay(20);
    Serial.begin(115200);
    Serial.println("\n\n\n\n-----------------------\nHệ thống bắt đầu!!!!");

    // Đợi 8 giây để mô-đun SIM khởi động
    delay(8000);
    simSerial.begin(MCU_SIM_BAUDRATE, SERIAL_8N1, MCU_SIM_RX_PIN, MCU_SIM_TX_PIN);

    // Kiểm tra lệnh AT
    sim_at_cmd("AT");

    // Thông tin sản phẩm
    sim_at_cmd("ATI");

    // Kiểm tra khe SIM
    sim_at_cmd("AT+CPIN?");

    // Kiểm tra chất lượng tín hiệu
    sim_at_cmd("AT+CSQ");

    sim_at_cmd("AT+CIMI");

    // Khai báo chân pin cảm biến lửa là đầu vào
    pinMode(FLAME_PIN, INPUT); 

    // Khai báo chân pin cảm biến MQ2 là đầu vào
    pinMode(MQ2_PIN, INPUT); 


    // Đợi 5 giây
    delay(5000);   
}

void loop() 
{     
    // Kiểm tra phát hiện lửa từ cảm biến lửa
    int flame_detected = digitalRead(FLAME_PIN);
    Serial.print("Trạng thái cảm biến lửa: ");
    Serial.println(flame_detected);
    delay (1000);
    if (flame_detected == FLAME_THRESHOLD) {
        Serial.println("Cảnh báo, Phát hiện lửa");
        sent_sms("Fire Detected");

        delay(5000); // Chờ đợi cho tin nhắn được gửi đi

        call(); // Thực hiện cuộc gọi
    } 

    // Kiểm tra phát hiện khí gas từ cảm biến MQ2
    int MQ2_value = analogRead(MQ2_PIN);
    Serial.print("Giá trị MQ2: ");
    Serial.println(MQ2_value);
    delay (1000);
    if (MQ2_value > MQ2_THRESHOLD) {
        Serial.println("Phát hiện rò rỉ khí gas");
        sent_sms("Gas leak");

        delay(5000); // Chờ đợi cho tin nhắn được gửi đi

        call(); // Thực hiện cuộc gọi
    } 

    // Giao tiếp với mô-đun SIM qua cổng Serial
    if (Serial.available()){
        char c = Serial.read();
        simSerial.write(c);
    }
    sim_at_wait();
}

Code mẫu MQTT gửi tọa độ GPS tới sever dùng 4G

Dưới đây là code mẫu dùng cho Mạch phát triển 4G GPS ESP32-C3 TDM2421, một số sản phẩm khác bạn cần tìm hiểu tập lệnh AT để chỉnh sửa cho phù hợp.

Sever ở đây mình dùng là Thingsboard, nếu dùng sever khác thì các bạn chỉnh TOPIC, ACESSTOKEN cho phù hợp.

Để sử dụng được MQTT cho module này, các lệnh AT cần thiết phải dùng là: 

  1. AT+QMTOPEN
  2. AT+QMTCONN
  3. AT+QMTPUBEX
  4. AT+QMTDISC

Lập trình

#include <HardwareSerial.h>

#define simSerial Serial0  // Sử dụng Serial0 cho module SIM
#define MCU_SIM_BAUDRATE 115200
#define MCU_SIM_TX_PIN 21
#define MCU_SIM_RX_PIN 20
#define MCU_SIM_EN_PIN 2  
#define BUF_SIZE 256
#define PAYLOAD_SIZE 128
#define MSG_SIZE 128

char data[BUF_SIZE];
char payload[PAYLOAD_SIZE];
char msg[MSG_SIZE];
float latDecimalGlobal = 0.0;
float lonDecimalGlobal = 0.0;
bool is_publishing = false;

// Hàm chuyển đổi tọa độ sang dạng thập phân
float convertToDecimal(char *coordinate, char direction) {
    float degrees, minutes, decimal;
    char degStr[4], minStr[10];

    if (strlen(coordinate) > 9) { // Kinh độ (DDDMM.MMMM)
        strncpy(degStr, coordinate, 3);
        degStr[3] = '\0';
        strcpy(minStr, coordinate + 3);
    } else { // Vĩ độ (DDMM.MMMM)
        strncpy(degStr, coordinate, 2);
        degStr[2] = '\0';
        strcpy(minStr, coordinate + 2);
    }

    degrees = atof(degStr);
    minutes = atof(minStr);
    decimal = degrees + (minutes / 60.0);

    if (direction == 'S' || direction == 'W') {
        decimal = -decimal;
    }

    return decimal;
}

// Hàm phân tích chuỗi GPS
void parseGPSData(char *gpsData) {
    char *token;
    char latitude[12], longitude[12];
    char latDir, lonDir;
    float latDecimal, lonDecimal;

    // Kiểm tra lỗi GPS hoặc dữ liệu không hợp lệ
    if (strstr(gpsData, "+CME ERROR:") != NULL) {
        Serial.print("GPS error: ");
        Serial.println(gpsData);
        // Tạo payload mặc định
        snprintf(payload, sizeof(payload), "{\"latitude\": %.6f, \"longitude\": %.6f}", latDecimalGlobal, lonDecimalGlobal);
        Serial.print("Payload (default): ");
        Serial.println(payload);
        return;
    }

    if (strstr(gpsData, "+QGPSLOC:") == NULL) {
        Serial.println("No valid GPS data found");
        // Tạo payload mặc định
        snprintf(payload, sizeof(payload), "{\"latitude\": %.6f, \"longitude\": %.6f}", latDecimalGlobal, lonDecimalGlobal);
        Serial.print("Payload (default): ");
        Serial.println(payload);
        return;
    }

    // Bỏ qua phần đầu "+QGPSLOC: "
    token = strtok(gpsData, " ");
    token = strtok(NULL, ",");
    // Bỏ qua thời gian
    token = strtok(NULL, ",");
    // Lấy vĩ độ
    strcpy(latitude, token);
    latDir = latitude[strlen(latitude) - 1];
    latitude[strlen(latitude) - 1] = '\0';
    // Lấy kinh độ
    token = strtok(NULL, ",");
    strcpy(longitude, token);
    lonDir = longitude[strlen(longitude) - 1];
    longitude[strlen(longitude) - 1] = '\0';
    // Chuyển đổi sang thập phân
    latDecimal = convertToDecimal(latitude, latDir);
    lonDecimal = convertToDecimal(longitude, lonDir);

    // Cập nhật biến toàn cục
    latDecimalGlobal = latDecimal;
    lonDecimalGlobal = lonDecimal;

    // In kết quả
    Serial.print("Vi do: ");
    Serial.println(latDecimal, 6);
    Serial.print("Kinh do: ");
    Serial.println(lonDecimal, 6);

    // Tạo payload JSON
    snprintf(payload, sizeof(payload), "{\"latitude\": %.6f, \"longitude\": %.6f}", latDecimalGlobal, lonDecimalGlobal);
    Serial.print("Payload: ");
    Serial.println(payload);
}

void sim_at_wait() {
    delay(1000); // Tăng delay để đảm bảo nhận đủ dữ liệu
    int len = 0;
    while (simSerial.available()) {
        char c = simSerial.read();
        if (len < BUF_SIZE - 1) {
            data[len++] = c;
        }
    }
    if (len > 0) {
        data[len] = '\0'; // Null-terminate chuỗi
        Serial.print("===== SIM receive: ");
        Serial.println(data);
        // Kiểm tra lỗi MQTT
        if (strstr(data, "+QMTSTAT:") != NULL) {
            Serial.print("MQTT connection error: ");
            Serial.println(data);
        }
        // Phân tích GPS nếu nhận được và không đang publish
        if (strstr(data, "+QGPSLOC:") != NULL && !is_publishing) {
            parseGPSData(data);
        } else if (strstr(data, "+CME ERROR:") != NULL) {
            parseGPSData(data); // Xử lý lỗi GPS
        }
    } else {
        Serial.println("No data received from SIM module");
    }
}

bool sim_at_cmd(String cmd) {
    Serial.print("Sending command: ");
    Serial.println(cmd);
    simSerial.println(cmd);
    sim_at_wait();
    // Kiểm tra phản hồi OK hoặc ERROR
    if (strstr(data, "OK") != NULL) {
        return true;
    } else if (strstr(data, ">") != NULL) {
        return true; // Dấu > cho biết module chờ payload
    } else if (strstr(data, "ERROR") != NULL) {
        Serial.print("Command failed: ");
        Serial.println(cmd);
        return false;
    }
    return false;
}

bool sim_at_send(char c) {
    simSerial.write(c);
    return true;
}

void get_gps_data() {
    Serial.println("Requesting GPS data...");
    sim_at_cmd("AT+QGPS?");
    for (int i = 0; i < 5; i++) { // Thử 5 lần
        Serial.print("GPS attempt ");
        Serial.println(i + 1);
        sim_at_cmd("AT+QGPSLOC=0");
        delay(5000); // Chờ 5 giây để GPS thử định vị
        if (strstr(data, "+QGPSLOC:") != NULL) {
            Serial.println("GPS data received!");
            break;
        }
    }
}

bool check_network() {
    sim_at_cmd("AT+CSQ");
    if (strstr(data, "+CSQ: 0,0") != NULL || strstr(data, "+CSQ: 99,99") != NULL) {
        Serial.println("No network signal!");
        return false;
    }
    Serial.println("Network signal OK");
    // Kiểm tra GPRS
    sim_at_cmd("AT+CGATT?");
    if (strstr(data, "+CGATT: 1") == NULL) {
        Serial.println("GPRS not attached, attempting to attach...");
        sim_at_cmd("AT+CGATT=1");
        delay(2000);
        return strstr(data, "OK") != NULL;
    }
    return true;
}

bool send_mqtt_data() {
    // Khởi tạo payload mặc định nếu rỗng
    if (strlen(payload) == 0) {
        snprintf(payload, sizeof(payload), "{\"latitude\": %.6f, \"longitude\": %.6f}", latDecimalGlobal, lonDecimalGlobal);
        Serial.print("Payload initialized: ");
        Serial.println(payload);
    }
    Serial.print("Sending MQTT data with payload: ");
    Serial.println(payload);
    is_publishing = true;

    if (!check_network()) {
        Serial.println("Network signal weak, skipping MQTT send");
        is_publishing = false;
        return false;
    }

    // Thử mở kết nối MQTT
    bool mqtt_opened = false;
    for (int i = 0; i < 3; i++) {
        if (sim_at_cmd("AT+QMTOPEN=0,\"demo.thingsboard.io\",1883")) { // CHỈNH SỬA CHO PHÙ HỢP VỚI SEVER ĐANG DÙNG
            if (strstr(data, "+QMTOPEN: 0,0") != NULL) {
                Serial.println("MQTT connection opened");
                mqtt_opened = true;
                break;
            }
        }
        Serial.println("MQTT open failed, retrying...");
        delay(3000);
    }
    if (!mqtt_opened) {
        Serial.println("Failed to open MQTT connection");
        is_publishing = false;
        return false;
    }

    // Thử kết nối client
    bool mqtt_connected = false;
    for (int i = 0; i < 3; i++) {
        if (sim_at_cmd("AT+QMTCONN=0,\"clientExample\",\"StQb4lQec7VJK7BZsUl5\"")) { // CHỈNH ACCESTOKEN CHO PHÙ HỢP
            if (strstr(data, "+QMTCONN: 0,0,0") != NULL) {
                Serial.println("MQTT client connected");
                mqtt_connected = true;
                break;
            }
        }
        Serial.println("MQTT connect failed, retrying...");
        delay(3000);
    }
    if (!mqtt_connected) {
        Serial.println("Failed to connect MQTT client");
        is_publishing = false;
        return false;
    }

    // Gửi payload
    bool mqtt_published = false;
    for (int i = 0; i < 3; i++) {
        uint32_t dodai = strlen(payload);
        snprintf(msg, sizeof(msg), "AT+QMTPUBEX=0,0,0,0,\"v1/devices/me/telemetry\",%lu", dodai); // CHỈNH TOPIC CHO PHÙ HỢP
        if (sim_at_cmd(msg)) {
            delay(1000); // Tăng delay để chờ dấu >
            if (strstr(data, ">") != NULL) {
                if (sim_at_cmd(payload)) {
                    delay(1000); // Tăng delay để gửi payload
                    sim_at_cmd(""); // Gửi \r\n
                    delay(1000); // Chờ phản hồi
                    if (strstr(data, "+QMTPUBEX: 0,0,0") != NULL) {
                        Serial.println("MQTT publish successful");
                        mqtt_published = true;
                        break;
                    }
                }
            }
        }
        Serial.println("MQTT publish failed, retrying...");
        delay(3000);
    }
    if (!mqtt_published) {
        Serial.println("Failed to publish MQTT data");
    }

    // Ngắt kết nối
    sim_at_cmd("AT+QMTDISC=0");
    delay(2000);
    is_publishing = false;
    return mqtt_published;
}

void setup() {
    pinMode(MCU_SIM_EN_PIN, OUTPUT);
    digitalWrite(MCU_SIM_EN_PIN, HIGH); // Thả PWRKEY lên cao
    delay(500);
    Serial.begin(115200);
    Serial.println("\n\n\n\n-----------------------\nSystem started!!!!");
    delay(5000);

    simSerial.begin(MCU_SIM_BAUDRATE, SERIAL_8N1, MCU_SIM_RX_PIN, MCU_SIM_TX_PIN);
    Serial.println("SIM Serial initialized!");
    Serial.println("Checking AT command...");
    sim_at_cmd("AT");
    Serial.println("Getting product info...");
    sim_at_cmd("ATI");
    Serial.println("Checking signal quality...");
    sim_at_cmd("AT+CSQ");
    Serial.println("Getting IMSI...");
    sim_at_cmd("AT+CIMI");
    Serial.println("Activating GPS...");
    sim_at_cmd("AT+QGPSCFG=\"antenna\",1"); // Bật nguồn cho anten chủ động
    sim_at_cmd("AT+QGPS=1");
    delay(15000); // Chờ 15 giây để GPS khởi động
    // Khởi tạo payload mặc định
    snprintf(payload, sizeof(payload), "{\"latitude\": %.6f, \"longitude\": %.6f}", latDecimalGlobal, lonDecimalGlobal);
    Serial.print("Initial payload: ");
    Serial.println(payload);
    get_gps_data();
}

void loop() {
    if (Serial.available()) {
        char c = Serial.read();
        sim_at_send(c);
    }
    if (!is_publishing) {
        get_gps_data(); // Đọc GPS trước khi gửi MQTT
    }
    send_mqtt_data();
    delay(5000);
}

Kết quả:  

Giao diện ThingsBoard sau khi nạp code. State “Active” đã hiển thị ở mục Device có Name là “MiHi” cho thấy module 
đã kết nối thành công tới ThingsBoard.

image.png

image.png

Hướng dẫn sử dụng module 4G với ESP32 – MQTT

Trong bài viết này mình sẽ hướng dẫn các bạn kết nối ESP với module 4G sử dụng giao thức PPPoS

Với việc sử dụng giao thức PPPoS, module SIM sẽ hoạt động như là 1 driver network giống như Wi-Fi, Ethernet.

1. Kết nối

ESP32 Module SIM
5V Vin
GND GND
GPIO 17 (MCU-TX) RX
GPIO 16 (MCU-RX)  TX
GPIO 15 (MCU-RX) PEN (Power Enable)

2. Code mẫu

ESP32 ESP-IDF:

ESP32 Arduino:

3. Test

Mình sử dụng ESP-IDF để test kết nối tới mqtt server test.mosquitto.org:1883

Hướng dẫn sử dụng:

Phần mềm AT Command Test

Tổng hợp tài liệu/software/driver cho các module sim

Document

Driver

Tool AT Command

Hardware

Code mẫu

Arduino

ESP32 (esp-idf)

MCU (STM32/WCH32/TI/NXP/Nuvoton/…)

Hướng dẫn cài đặt driver module SIM 4G cho Linux/Windows

1. Các loại chế độ hoạt động của module 4G và cách chuyển chế độ hoạt động

Các module 4G hỗ trợ các driver cơ bản như sau:

Tùy từng loại module mà có cách chuyển đổi khác nhau (tham khảo at command manual và Linux USB Application Note của từng hãng:

Tham khảo tài liệu:

A76XX Series_Linux_USB_Application Note_V1.00.pdf

SIM7500_SIM7600 Linux NDIS User Guide_V2.01.pdf

https://www.waveshare.com/wiki/SIM7600G-H_4G_DONGLE

Ví dụ:

1. Windows

2. Ubuntu/Raspberry pi

ls /dev/ttyUSB*

ip a // kiểm tra xem có interface usb* không
ping 8.8.8.8 -Iusb0

3. Orange pi/build root/yocto/Android/Openwrt

Hướng dẫn cài đặt driver USB DONGLE

Windows (Win10/Win11)

A7670/A7672/A7600C-L1

SIM7600

Linux (Ubuntu/Debian/…)

ip a

And check the usb0 interface

sudo dhclient -v usb0

sudo route add -net 0.0.0.0 usb0

Sau khi cài driver và set up như trên chúng ta sẽ dùng phần mềm AT command Test của chúng tôi để cài đặt chế độ internet cũng như test các chức năng khác. Download tại đây

Nếu chưa tự động nhận internet, hãy gửi 2 lệnh sau bằng AT command
AT+DIALMODE=0
AT$MYCONFIG=”usbnetmode”,0

Xem thêm:
– Hướng dẫn sử dụng phần mềm AT Command Test