You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino MKR NB 1500收发数次MQTT消息后卡顿的原因排查

解决Arduino MKR NB 1500卡在serializeJson的问题

核心原因分析

MKR NB 1500的GSM模块在内存、带宽和串口缓冲区上的资源远不如MKR WiFi 1010,你的大JSON序列化+MQTT发送逻辑在资源受限的GSM环境下出现了阻塞或内存问题。

具体排查与修复步骤

1. 调整缓冲区大小适配大消息

  • PubSubClient缓冲区:默认仅128字节,无法承载你的大JSON,初始化时手动扩容:
    PubSubClient client(nbClient);
    client.setBufferSize(4096); // 适配12KB级别的JSON消息
    
  • BufferingPrint缓冲区:当前32字节太小,会频繁触发底层GSM串口发送,大幅增加阻塞概率,调至256或512字节:
    BufferingPrint bufferedClient{client, 512};
    

2. 优化内存使用避免碎片化

  • 去掉冗余String转换:循环中把浮点数转String的操作会大量占用堆内存,还容易导致内存碎片化。直接让ArduinoJson处理浮点数,序列化时指定精度即可:
    // 替换原循环中的String转换代码
    obj["pwr"] = coffeeInfo[i].pwr;
    obj["t1"] = coffeeInfo[i].t1;
    obj["t2"] = coffeeInfo[i].t2;
    // 序列化时控制浮点数精度
    serializeJson(coffeeDoc, bufferedClient, SerializeOption::Precision(1));
    
  • 改用StaticJsonDocument:如果JSON结构和大小固定,用静态分配的文档替代DynamicJsonDocument,减少堆内存分配和碎片:
    StaticJsonDocument<12288> coffeeDoc; // 替换DynamicJsonDocument
    

3. 添加调试追踪定位问题

在关键步骤插入串口打印,精准确认阻塞位置:

// 序列化前后加日志
Serial.println("[DEBUG] Starting JSON serialization...");
serializeJson(coffeeDoc, bufferedClient, SerializeOption::Precision(1));
Serial.println("[DEBUG] Serialization completed");

// 发送前检查GSM连接状态
if (!nb.isConnected()) {
  Serial.println("[DEBUG] Reconnecting GSM module...");
  while (!nb.connect()) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("\n[DEBUG] GSM reconnected");
}

// 打印剩余内存排查泄漏
Serial.print("[DEBUG] Free RAM: ");
Serial.println(freeMemory()); // 需要包含<avr/pgmspace.h>

4. 完善MQTT发送容错逻辑

检查client.beginPublish的返回值,避免无意义的后续操作:

if (client.beginPublish("device/coffee", measureJson(coffeeDoc), false)) {
  // 执行序列化与发送
  bufferedClient.flush();
  client.endPublish();
} else {
  Serial.println("[ERROR] Failed to start MQTT publish");
  // 可在此添加重试逻辑
}

修改后的完整代码片段

// 初始化时配置PubSubClient缓冲区
PubSubClient client(nbClient);
client.setBufferSize(4096);

// ...其他初始化代码...

// 发送逻辑部分
if (!nb.isConnected()) {
  Serial.println("[DEBUG] Reconnecting GSM...");
  while (!nb.connect()) {
    delay(1000);
  }
}

StaticJsonDocument<12288> coffeeDoc;
coffeeDoc["device"]["id"] = boardID;
JsonObject transaction = coffeeDoc.createNestedObject("transaction");
transaction["id"] = j;
JsonArray transaction_data = transaction.createNestedArray("data");

for(int i = 0; i < total; i++){         
  JsonObject obj = transaction_data.createNestedObject();
  obj["id"] = i;
  obj["ts"] = coffeeInfo[i].ts;
  obj["pwr"] = coffeeInfo[i].pwr;
  obj["t1"] = coffeeInfo[i].t1;
  obj["t2"] = coffeeInfo[i].t2;
  obj["extruder"] = coffeeInfo[i].extruder;
  obj["time"] = coffeeInfo[i].time;
}

Serial.println("[DEBUG] Starting MQTT publish...");
if (client.beginPublish("device/coffee", measureJson(coffeeDoc), false)) {
  BufferingPrint bufferedClient{client, 512};
  Serial.println("[DEBUG] Serializing JSON...");
  serializeJson(coffeeDoc, bufferedClient, SerializeOption::Precision(1));
  Serial.println("[DEBUG] Serialization done");
  bufferedClient.flush();
  client.endPublish();
  Serial.println("[DEBUG] Publish completed");
  j++;
} else {
  Serial.println("[ERROR] Publish initiation failed");
}
coffeeDoc.clear();

内容的提问来源于stack exchange,提问作者AleG94

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 09:48:28