c++ - atmega328P+ENC28J60运行12小时卡死

标签 c++ json arduino ethernet

我对以太网世界还很陌生。因此,如果我提出愚蠢的问题,请多多包涵。

我使用 Atmega328P+ENC28J60 芯片设计了一个 PCB(原理图附在下图中 - sch1、sch2)。该板的功能基本上是向服务器发送 GET 请求并检索一组 json 数据以打开输出引脚,因此根据我的理解,我的板仅充当客户端,对吗?代码附在下面:

#include <EEPROM.h>
#include <ArduinoJson.h>
#include <EthernetENC.h>

#define OUT0    2
#define OUT1    A3
#define OUT2    A2
#define OUT3    A1
#define OUT4    A0
#define OUT5    9
#define OUT6    8
#define OUT7    7
#define OUT8    6
#define OUT9    5
#define CS      10

// mac: 46 57 5a 6b 48 51
#define HOSTNAME  "autolighting.afa-sports.com"

#define ID_SIZE   6

static byte mac[ID_SIZE];
static char macBuffer[ID_SIZE*2+1];
const byte output[] PROGMEM = {OUT0, OUT1, OUT2, OUT3, OUT4, OUT5, OUT6, OUT7, OUT8, OUT9};
EthernetClient client;

void clientRead() {
  StaticJsonDocument<40> filter;
  StaticJsonDocument<120> doc;
  filter.clear();
  doc.clear();
  filter["data"]["relay_actions"] = true;

  client.find("\r\n\r\n");
  deserializeJson(doc, client, DeserializationOption::Filter(filter));
  client.flush();
  delay(50);

  if (!doc["data"]["relay_actions"].isNull()) {
    for (byte i = 0; i < 10; i++) {
//      Serial.print(doc["data"]["relay_actions"][i].as<bool>());
      digitalWrite(pgm_read_byte_near(&output[i]), doc["data"]["relay_actions"][i].as<bool>());
    }
//    Serial.println();
  }
  
  filter.clear();
  doc.clear();
}

void sendReq() {
  client.println(F("GET /api/iot/master-controller/get-command HTTP/1.1"));
  client.println(F("Host: autolighting.afa-sports.com"));
//  client.println(F("DEVICE-ID: 46575a6b4851"));
  client.print(F("DEVICE-ID: "));
  client.println(macBuffer);
  client.println(F("Connection: close"));
  client.println();
}

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

  for (byte i = 0; i < 10; i++) {
    pinMode(pgm_read_byte_near(&output[i]), OUTPUT);
    digitalWrite(pgm_read_byte_near(&output[i]), LOW);
  }
  
  for (uint8_t i = 0; i < ID_SIZE; i++) {
    byte charByte = EEPROM.read(i);
    if (charByte != 0) {
      char temp[2];
      mac[i] = charByte;
      itoa(mac[i], temp, 16);
      strcat(macBuffer, strlwr(temp));    // REMOVE strlwr IN RELEASE VERSION
      free(temp);
      delay(10);
    }
  }
  strcat(macBuffer, '\0');

  Ethernet.init(CS);
  while (!Ethernet.begin(mac));
  client.setTimeout(5000);
  delay(1000);
}

void loop() {
  while (!Ethernet.begin(mac));   // init fail

  delay(1000);
  if (client.connect(HOSTNAME, 80)) {
    sendReq();
    clientRead();
    client.stop();
  }
  delay(3000);
}

由于 SRAM 消耗量大,而且我将来可能还有其他东西(还不确定)要添加到开发板上,我尝试通过更改此设置(在 uipethernet-conf.h 文件中)来最小化动态内存):

#define UIP_SOCKET_NUMPACKETS    5
#define UIP_CONF_MAX_CONNECTIONS 4
#define UIP_CONF_UDP_CONNS       4

为此:

#define UIP_SOCKET_NUMPACKETS    2
#define UIP_CONF_MAX_CONNECTIONS 2
#define UIP_CONF_UDP_CONNS       1

我想知道这会影响系统性能吗?顺便说一句,我还将超时设置为 5 秒

经过 13 小时的平稳运行后,电路板死机,只有在我硬重置电路板时才恢复正常。目前,我正在将电路板连接到无线扩展器,因为我没有坐在 wifi 路由器旁边。在我看来这像是一个内存泄漏问题,但内存泄漏问题是否仍然存在于最新的 ArduinoJson 和 EthernetENC/UIPEthernet 库中?

P/S: 之前用的是UIPEthernet.h,后来有人指导我试用了EthernetENC库,内存消耗确实下降了一些,但是卡顿问题依旧存在

请随时指出我犯的任何错误,仍在学习冒险中。 =) 非常感谢您的帮助。非常感谢。

库版本:

  • ArduinoJson 6.17.2
  • 以太网ENC 2.0.0
  • UIPEthernet 2.0.9

示意图: sch1 sch2

最佳答案

没有这些硬件,只能根据您的代码和 Arduino 引用进行分析。

来自您的代码

    while (!Ethernet.begin(mac));   // init fail

在以下情况下“可能”导致卡住:

  1. Ethernet.begin 总是返回 false
  2. Ethernet.begin“可以”调用多次吗?

这些是一些可能有帮助的引用:

Arduino DHCP failed to configure

https://electronics.stackexchange.com/questions/67045/ethernet-begin-only-works-with-sd-card-removed-why

根据维基:

https://github.com/jandrassy/EthernetENC/wiki/Examples

你应该使用:

  1. 以太网.maintain();

  2. client.available();

  3. 编写自己的延迟函数:

    void mDelay(unsigned long milliseconds) {
      const unsigned d = 1;
      while (milliseconds > d) {
        Ethernet.maintain();
        delay(d);
        milliseconds -= d;
      }
      Ethernet.maintain();
      delay(milliseconds);
    }

注意:对于 arduino 或电子产品问题,可能是 https://electronics.stackexchange.com/ 是一个更合适的网站。

关于c++ - atmega328P+ENC28J60运行12小时卡死,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64896657/

相关文章:

c - 定义C中用于存储的枚举的数据类型

c++ - 为什么 const 左值引用在重载解析期间优先于 const 右值引用

c++ - std::print() 线程安全吗?它是否存在文本交错问题?

c++ - Qt QTextEdit 添加虚假行

mysql - 如何从 node.js 中的 mysql 获取最近添加的重新编码 ID

json - 在不触及所有字段的情况下编码和解码 JSON 主体

ruby - 获取谷歌搜索结果的正确方法是什么?

c++ - Arduino 结构变量似乎在没有明确重新分配的情况下被重新分配

python - 从 Python 3 控制 Arduino 继电器

c++ - 爬取 Windows 程序菜单信息 C++