【问题标题】:save data every 3 second and send an array every 5 minutes每 3 秒保存一次数据,每 5 分钟发送一个数组
【发布时间】:2021-03-08 09:45:06
【问题描述】:

我有一个连接到 wemos d1 mini 的 MPU。传感器发送 3 个值:X、Y 和 Z 轴。由于我的项目是太阳能供电的,因此我需要降低功耗。为了做到这一点,我想每 3 秒读取一次 MPU 的 3 个值,将这些值存储在一个数组中,并在采样 5 分钟后打开 wifi 并通过 mqtt 将数组发送到我的主题。

我已经测试了我的代码的每一部分并且一切正常。 例如,如果我尝试发送一个包含三个对象的数组,它可以完美地工作 但是当我尝试发送一个包含 100 个对象的数组时,它不起作用。

(注意:上面的“100”是从哪里来的?如果我需要每 5 分钟发送一次数据,而我在这里每 3 秒读取一次值,我就有 100 个采样)

希望有人能帮忙

unsigned long t_start;

void setup()
{
    t_start = millis();
}
//compute the required size
const size_t CAPACITY = JSON_ARRAY_SIZE(100) + 100 * JSON_OBJECT_SIZE(3);
//allocate the memory for the document
StaticJsonDocument<CAPACITY> doc;

//MPU
const int MPU = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ;

void loop()
{
    //Create an empty array
    JsonArray arr = doc.to<JsonArray>();

    if (millis() - t_start >= 3000) {
        for (int i = 0; i < 100; i++) {

            //MPU reading
            Wire.beginTransmission(MPU);
            Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
            Wire.endTransmission(false);
            Wire.requestFrom(MPU, 14, true); // request a total of 14 registers
            AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
            AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
            AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

            //Create a JSON Object
            JsonObject obj = doc.createNestedObject();
            obj["AcX"] = AcX;
            obj["AcY"] = AcY;
            obj["AcZ"] = AcZ;
        }

        t_start = millis();
    }
}

//MQTT PUBLISHING JSON PACKAGE
char mqttData[MQTT_BUFFER];
serializeJson(doc, mqttData);
Serial.println(mqttData);
int ret = client.publish("esp8266/JSON", mqttData);
} //end of loop

【问题讨论】:

  • 你到底在问什么?您的代码行为与您的预期有何不同?请阅读How to Ask
  • @Piglet 已编辑。我不知道如何更好地解释它。你不能理解什么?也许我可以改变
  • 可能您的 MQTT Keep-Alive 间隔小于 5 分钟,例如60 年代。
  • “它不起作用”信息量不是很大。任何自己的调试尝试呢?如果它不适用于 100 并且适用于 3,那么它开始失败的数字是多少? MQTT是否会失败,或者如果您只是将其打印到串行?这不是调试服务,因此我们鼓励人们缩小问题范围。
  • 所以您想每 3 秒测量一次?为什么有一个循环尽可能快 100 倍?也是在循环内发布的代码吗?我可以看到 3 个开始 { 和四个结束 }

标签: arduino esp8266


【解决方案1】:

如果您希望每 3 秒测量一次而不是每 3 秒测量 100 次,代码应如下所示:

#define MQTT_KEEPALIVE 300
// headers ...
// setup() ...

void loop() {
  //Create an empty array
  JsonArray arr = doc.to<JsonArray>();

  static auto t_start = millis(); // static will preserve last value even after exiting loop

  int8_t count = 0;
  while (count < 100) { // stays here whole 300s, so if the keep alives are needed or doing something else, it should be inside too
    client.loop(); // sugested in comments

    if (millis() - t_start >= 3000) {
      t_start += 3000;
      ++count;

      //MPU reading
      Wire.beginTransmission(MPU);
      Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission(false);
      Wire.requestFrom(MPU, 14, true); // request a total of 14 registers
      AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
      AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
      AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

      //Create a JSON Object
      JsonObject obj = doc.createNestedObject();
      obj["AcX"] = AcX;
      obj["AcY"] = AcY;
      obj["AcZ"] = AcZ;
    }

    // handling keep alives every X seconds as it's unlikely as long as 300s:
    // if (...) sendKeepAlive();
  }
  
  // after 100 measures it'll get here:

  //MQTT PUBLISHING JSON PACKAGE
  char mqttData[MQTT_BUFFER];
  serializeJson(doc, mqttData);
  Serial.println(mqttData);
  int ret = client.publish("esp8266/JSON", mqttData);
} //end of loop

但是,它应该只解决代码中最明显的问题。可能还有其他的,比如缓冲区可能太小,或者......

而且它未经测试,我没有这个硬件设置

【讨论】:

  • 现在在串行监视器上我收到此错误 "rst cause:2, boot mode:(3,6)"
  • 可能是 wdt 超时或者它必须更​​频繁地离开循环(wdt,wifi 处理)
  • 是的,绝对是 wdt。我不确定如何处理没有泄漏的清除 json 文档,因此将所有度量值存储到数组中并在最后创建该 json 可能是合理的
  • mqttClient.loop(); 添加到loop() 的开头。此外,如果您仅每 5 分钟发布一次 MQTT 消息,请在代码开头添加 define MQTT_KEEPALIVE 300(默认为 15 秒)以防止服务器连接超时。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-20
  • 2011-09-28
相关资源
最近更新 更多